请记住,浮点数只是尾数系数,乘以 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);
所以,总而言之,不,这并不比你自己的解决方案短,但我认为这是你能做到的最好的。您必须生成 52 个随机位,这些位需要从 32 位块构建,然后需要向下移回 1 以下。