简体   繁体   English

Math.random() 不满意

[英]Math.random() unsatisfactory

Let be a list containing the 26 letters of the alphabet from A to Z. We mix the list with the Fisher-Yates algorithm (see https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle ).让我们成为一个包含从 A 到 Z 的 26 个字母的列表。我们将列表与 Fisher-Yates 算法混合(参见https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle )。 We are interested in the first letter of the table:我们对表格的第一个字母感兴趣:

  • In theory, each letter has the same probability of being in the first position: 1/26 ~ 3.85%.理论上,每个字母出现在第一个 position 的概率相同:1/26 ~ 3.85%。
  • In practice, this is not the case, As the distribution below shows.实际上,情况并非如此,如下面的分布所示。 the probability of finding B is 5.14% against 2.89% for Z. B has 1.78x more chances than Z to be in first position (almost 2x more which is huge)找到 B 的概率为 5.14%,而 Z 的概率为 2.89%。B 出现在第一个 position 中的机会比 Z 多 1.78 倍(几乎是 2 倍,这是巨大的)

分配

Here is the code I used:这是我使用的代码:

"use strict";

// mix
const mix = array => {
    const { length: n } = array;
    for (let i = 0; i < n; i++) {
        const x = Math.floor(Math.random() * n);
        [array[i], array[x]] = [array[x], array[i]];
    }
    return array;
};

const A = 'A'.charCodeAt(0);
const NB_LETTERS = 26;

const TABLE = {};
for (let i = 0; i < NB_LETTERS; i++) TABLE[String.fromCharCode(A + i)] = 0;

for (let N = 1; ; N++) {

    // init
    const array = [];
    for (let i = 0; i < NB_LETTERS; i++) array[i] = String.fromCharCode(A + i);

    mix(array);

    TABLE[array[0]]++;

    if (N % 1000000 === 0) {
        console.log('');
        console.log("N =", N);
        console.log(
            Object.entries(TABLE)
                .map(([letter, n]) => {
                    const freq = n / N;
                    return letter + '\t' + freq.toString().replace('.', ',');
                })
                .join('\n')
        );
    }
}

Questions:问题:

  • Do you get the same results?你得到相同的结果吗?
  • Is it from Math.random() ?它来自Math.random()吗? I think so... do you know of an alternative that would give a uniform distribution?我想是的...您知道可以提供均匀分布的替代方案吗?

Thanks in advance提前致谢

The shuffle algorithm in the function mix is not correctly implemented. function mix中的 shuffle 算法未正确实现。

The algorithm in the referenced Wikipedia article stipulates that the range to take a random number from should be different in each iteration, which is not the case in your implementation, hence the non-homogeneous distribution.引用的 Wikipedia 文章中的算法规定,在每次迭代中取随机数的范围应该不同,这在您的实现中并非如此,因此是非均匀分布。

Make this correction:进行此更正:

    const x = i + Math.floor(Math.random() * (n - i));

Other implementations (with some optimisations) can be found at How to randomize (shuffle) a JavaScript array?其他实现(有一些优化)可以在如何随机化(随机播放)JavaScript 阵列中找到?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM