[英]Math.random() unsatisfactory
让我们成为一个包含从 A 到 Z 的 26 个字母的列表。我们将列表与 Fisher-Yates 算法混合(参见https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle )。 我们对表格的第一个字母感兴趣:
这是我使用的代码:
"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')
);
}
}
问题:
Math.random()
吗? 我想是的...您知道可以提供均匀分布的替代方案吗?提前致谢
function mix
中的 shuffle 算法未正确实现。
引用的 Wikipedia 文章中的算法规定,在每次迭代中取随机数的范围应该不同,这在您的实现中并非如此,因此是非均匀分布。
进行此更正:
const x = i + Math.floor(Math.random() * (n - i));
其他实现(有一些优化)可以在如何随机化(随机播放)JavaScript 阵列中找到?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.