浮動小数点数は単なる仮数係数であり、2 を指数に累乗したものであることに注意してください。
floating_point_value = mantissa * (2 ^ exponent)
を使用Math.random
すると、32 ビットのランダムな仮数を持ち、常にの指数を持つ浮動小数点が生成されます-32
。したがって、小数点以下の桁数は左に 32 桁にビット シフトされるため、仮数は小数点以下の桁の左側には決してありません。
mantissa = 10011000111100111111101000110001 (some random 32-bit int)
mantissa * 2^-32 = 0.10011000111100111111101000110001
数回実行Math.random().toString(2)
して、これが事実であることを確認してください。
解決策:ランダムな 32 ビットの仮数を生成し、次のように掛けることができますMath.pow(2,-32)
。
var arr = new Uint32Array(1);
crypto.getRandomValues(arr);
var result = arr[0] * Math.pow(2,-32);
// or just arr[0] * (0xffffffff + 1);
浮動小数点には均等な分布がないことに注意してください (仮数の精度が不足しているため、可能な値は数が大きくなるほどまばらになります)、非常に強力な乱数を必要とする暗号化アプリケーションやその他のドメインには適していません。 . そのためには、 によって提供される生の整数値を使用する必要がありますcrypto.getRandomValues()
。
編集:
JavaScript の仮数部は 52 ビットであるため、52 ビットの乱数を得ることができます。
var arr = new Uint32Array(2);
crypto.getRandomValues(arr);
// keep all 32 bits of the the first, top 20 of the second for 52 random bits
var mantissa = (arr[0] * Math.pow(2,20)) + (arr[1] >>> 12)
// shift all 52 bits to the right of the decimal point
var result = mantissa * Math.pow(2,-52);
つまり、全体として、いいえ、これはあなた自身のソリューションよりも短くはありませんが、それがあなたが望むことができる最善の方法だと思います. 32 ビット ブロックから構築する必要がある 52 のランダム ビットを生成し、1 未満に戻す必要があります。