Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用window.crypto.getRandomValues获取特定范围内的随机值_Javascript_Java_Random - Fatal编程技术网

Javascript 如何使用window.crypto.getRandomValues获取特定范围内的随机值

Javascript 如何使用window.crypto.getRandomValues获取特定范围内的随机值,javascript,java,random,Javascript,Java,Random,我们一直在使用Math.random获得4000-64000之间的随机数: Math.floor(Math.random() * 60000 + 4000); 我们现在必须用一个更加密的随机数生成器来代替它。在对这个问题进行研究之后,我们决定同意 window.crypto.getRandomValues。我不知道如何使用它来获得特定范围内的随机数。请有人帮忙。对于给定的最小值和最大值,该公式描述了如果您一次请求u位,并且如果返回结果会引入偏差,则重试,您将平均使用多少位 幸运的是,最佳策略只

我们一直在使用Math.random获得4000-64000之间的随机数:

Math.floor(Math.random() * 60000 + 4000);
我们现在必须用一个更加密的随机数生成器来代替它。在对这个问题进行研究之后,我们决定同意
window.crypto.getRandomValues。我不知道如何使用它来获得特定范围内的随机数。请有人帮忙。

对于给定的最小值和最大值,该公式描述了如果您一次请求
u
位,并且如果返回结果会引入偏差,则重试,您将平均使用多少位

幸运的是,最佳策略只是一次请求
ceil(log2(max-min+1))
位。无论如何,我们只能使用
crypto.getRandomValues
获取完整字节,因此,如果每个函数调用一次
crypto.getRandomValues
,我们能做的最好的事情是:

// Generate a random integer r with equal chance in  min <= r < max.
function randrange(min, max) {
    var range = max - min;
    if (range <= 0) {
        throw new Exception('max must be larger than min');
    }
    var requestBytes = Math.ceil(Math.log2(range) / 8);
    if (!requestBytes) { // No randomness required
        return min;
    }
    var maxNum = Math.pow(256, requestBytes);
    var ar = new Uint8Array(requestBytes);

    while (true) {
        window.crypto.getRandomValues(ar);

        var val = 0;
        for (var i = 0;i < requestBytes;i++) {
            val = (val << 8) + ar[i];
        }

        if (val < maxNum - maxNum % range) {
            return min + (val % range);
        }
    }
}

//生成一个随机整数r,其最小值的概率相等一个简单的数学替换。随机数可能如下所示:

/**
 * Return values in the range of [0, 1)
 */
const randomFloat = function () {
  const int = window.crypto.getRandomValues(new Uint32Array(1))[0]
  return int / 2**32
}
要将其扩展到整数,请执行以下操作:


/**
 * Return integers in the range of [min, max)
 *
 * @todo check that min is <= max.
 */
const randomInt = function (min, max) {
  const range = max - min
  return Math.floor(randomFloat() * range + min)
}

/**
 * Generate an array of integers in the range of [min, max).
 */
const randomIntArray = function (length, min, max) {
  return new Array(length).fill(0).map(() => randomInt(min, max))
}
生成包含0到2(含0到2)的十个整数的数组:

randomIntArray(10, 0, 3)

@Deele此答案中的代码会自动缩放数组大小。如果生成大量随机数,并且范围很小,则在较大的数据块中请求随机性并更仔细地提取它可能很有用。很难确定具体的数字,但我会开始优化,比如说,每秒100个请求,或者说,如果你只是掷硬币的话,是10/s。@caw我想你得到了最大的不同。由于JavaScript解释器并不总是实现尾部递归调用,因此递归解决方案可能会遇到堆栈边界。递归通常也较慢,因为在没有优化的情况下会分配堆栈帧。js解决方案还会在每个递归步骤中重做所有计算,这是不必要的。通过使用标识
2^8x=256^x
,我的解决方案保存了一个变量和两条指令。他们的代码平均需要更多的尝试:对于min=1 max=3,他们有1/4的机会必须重试。我的代码只在1/256中重试。特别是,最终条件
val+range-(val%range)
如何等同于
val<(数学地板(maxNum/range)*range)
?我看到这是一个扩展范围的拒绝采样,这必须是我们可以安全地应用模而不引入偏差的条件。但我不明白这些条件是如何等价的。对不起,这是最后一句话!;)@据我所知,OpenWireless项目已经失败了。您的建议(或更简单的等效值
val
)是正确的。我最初的检查并没有引入抽样偏差,但丢弃了可能得到的结果(例如
val=255 range=1 maxNum=256
。我已经更新了答案。。此答案中的函数从范围中排除
max
,但包括
min
。若要解决此问题,请将
var range=max-min;
更改为
var range=max-min+1;
另请参阅和
[0, 2, 1, 2, 0, 0, 1, 0, 1, 0]