Javascript:使用crypto.getRandomValues在一个范围内生成一个随机数

问题描述 投票:10回答:2

我知道你可以使用这个函数在一个范围内的JavaScript中生成一个随机数:

function getRandomInt (min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

由IonuţG。Stan here提供。

我想知道的是你是否可以使用crypto.getRandomValues()而不是Math.random()在一个范围内生成更好的随机数。我希望能够生成0到10之间的数字,或0到1,甚至10 - 5000(含)。

你会注意到Math.random()产生一个如下数字:0.8565239671015732。

getRandomValues API可能会返回以下内容:

  • 231与Uint8Array(1)
  • 54328与Uint16Array(1)
  • 355282741与Uint32Array(1)

那么如何将其转换回十进制数,以便我可以使用上面相同的范围算法?或者我需要一个新的算法?

这是我尝试的代码,但它不能很好地工作。

function getRandomInt(min, max) {       
    // Create byte array and fill with 1 random number
    var byteArray = new Uint8Array(1);
    window.crypto.getRandomValues(byteArray);

    // Convert to decimal
    var randomNum = '0.' + byteArray[0].toString();

    // Get number in range
    randomNum = Math.floor(randomNum * (max - min + 1)) + min;

    return randomNum;
}

在低端(范围0 - 1),它返回0比1更多。使用getRandomValues()执行此操作的最佳方法是什么?

非常感谢

javascript random cryptography range
2个回答
13
投票

最简单的方法可能是拒绝抽样(参见http://en.wikipedia.org/wiki/Rejection_sampling)。例如,假设max - min小于256:

function getRandomInt(min, max) {       
    // Create byte array and fill with 1 random number
    var byteArray = new Uint8Array(1);
    window.crypto.getRandomValues(byteArray);

    var range = max - min + 1;
    var max_range = 256;
    if (byteArray[0] >= Math.floor(max_range / range) * range)
        return getRandomInt(min, max);
    return min + (byteArray[0] % range);
}

7
投票

恕我直言,[min..max]描述了使用window.crypto.getRandomValues()here范围内生成随机数的最简单方法。

ECMAScript 2015语法代码,以防链接为TL; TR:

function getRandomIntInclusive(min, max) {
    const randomBuffer = new Uint32Array(1);

    window.crypto.getRandomValues(randomBuffer);

    let randomNumber = randomBuffer[0] / (0xffffffff + 1);

    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(randomNumber * (max - min + 1)) + min;
}
© www.soinside.com 2019 - 2024. All rights reserved.