如何使用crypto.getRandomValues中的随机数随机化数组

How to randomize an array with random numbers from crypto.getRandomValues?

本文关键字:随机数 随机化 数组 何使用 crypto getRandomValues      更新时间:2023-09-26

我知道您可以使用Fisher Yates shuffle在JavaScript中打乱数组。然而,它使用Math.random作为随机数。我想知道你是否可以使用window.crypto.getRandomValues()为随机数源获得更好的洗牌?

我试过低于这个标准。getRandomIntInRange()函数使用拒绝采样和此处指定的示例。

请告诉我这是否是正确的方法,或者你是否能想出更好的方法。

$(document).ready(function()
{
    var dataArray = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14'];               
    var shuffledArray = shuffleArray(dataArray);                
    console.log(shuffledArray);
});         
function getRandomIntInRange(min, max) {
    var range = max - min + 1;
    var maxRange = 256;
    var byteArray = new Uint8Array(1);
    // Fill byteArray with 1 random number
    window.crypto.getRandomValues(byteArray);
    // If outside of range, get another
    if (byteArray[0] >= Math.floor(maxRange / range) * range)
    {
        return getRandomIntInRange(min, max);
    }
    return min + (byteArray[0] % range);
}
function shuffleArray(dataArray) {
    var counter = dataArray.length, temp, index;
    while (counter > 0)
    {
        index = getRandomIntInRange(0, counter - 1);
        counter--;
        temp = dataArray[counter];
        dataArray[counter] = dataArray[index];
        dataArray[index] = temp;
    }
    return dataArray;
}

这段代码没有错(尽管对数字1到14使用字符串似乎毫无意义地缓慢和复杂——仅仅对数字1和14有什么错?)。你当然可以自由使用任何你喜欢的RNG算法。但不同的算法被设计成最适合不同的任务。一般来说,为模拟设计的RNG对于密码学来说是不安全的;加密安全的RNG对于模拟来说是可以接受的,但可能太慢了。如果你只想玩几个游戏,没问题。但是,如果你想模拟十亿只手的21点或扑克,或者用数十亿个数据点进行蒙特卡洛集成,使用加密RNG很可能会让你的代码从几分钟内运行变成几周内运行,但没有任何好处。