请记住,浮点数只是一个mantissa系数,乘以 2 得出exponent:
floating_point_value = mantissa * (2 ^ exponent)
With Math.random
,您生成具有 32 位随机尾数的浮点,并且always有一个指数-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);
Note浮点不具有均匀分布(由于尾数缺乏精度,数字越大,可能的值变得越稀疏),使得它们不适合加密应用程序或需要非常强的随机数的其他领域。为此,您应该使用由提供给您的原始整数值crypto.getRandomValues()
.
EDIT:
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);
所以,总而言之,不,这并不比您自己的解决方案短,但我认为这是您希望做的最好的事情。您必须生成 52 个随机位,这些随机位需要从 32 位块构建,然后需要移回到 1 以下。