Javascript 为什么这种随机化方法会产生扭曲的结果?
我使用了两种不同的随机化方法,其中一种方法给出的结果的方差是我所期望的,而另一种方法给出的结果是有偏差的,并且也是非常一致的 方法:Javascript 为什么这种随机化方法会产生扭曲的结果?,javascript,random,Javascript,Random,我使用了两种不同的随机化方法,其中一种方法给出的结果的方差是我所期望的,而另一种方法给出的结果是有偏差的,并且也是非常一致的 方法: function randomA() { var raw = Number((Math.random()+'').substr(2)); return raw % NUM_OF_POSSIBLES; } function randomB() { var raw = Math.round(Math.random()*10000);
function randomA() {
var raw = Number((Math.random()+'').substr(2));
return raw % NUM_OF_POSSIBLES;
}
function randomB() {
var raw = Math.round(Math.random()*10000);
return raw % NUM_OF_POSSIBLES;
}
当NUM\u OF\u POSSIBLES=2
时,第一种方法(randomA()
)会产生相当一致的零数(64%)和36%的1。而radnomB()。
如果NUM\u OF\u POSSIBLES=5
第一种方法再次以相当一致的方式倾斜:
0:10%,1:23%,2:22%,3:22%,4:23%,而第二种方法给出了每个结果的20%左右
您可以在此处找到包含多个测试的完整代码:
为什么第一个方法是倾斜的,为什么倾斜是一致的?我不完全确定,但我猜这与JavaScript将数字格式化为字符串时使用的舍入模式有关。在第一种情况下,您的结果取决于最后一位数字的选择,这对舍入非常敏感。如果它偏向于偶数,这可以解释你的结果。(在NUM\u of_POSSIBLES==5的情况下,这可能是因为最后一个数字缺少5s。)在第二个例程中,结果取决于字符串表示的中间数字,这几乎与该影响无关
在第一个例行程序中,切掉最后一两个数字可能会有更好的结果
编辑我刚刚通过实验确认,如果将第一个例程更改为切掉最后一个数字:
function randomA() {
var raw = String(Math.random());
raw = raw.substring(2, raw.length-1);
return raw % NUM_OF_POSSIBLES;
}
然后,当NUM\u OF_POSSIBLES==2
或5
时,这种偏差似乎消失了。我发现,随机数以这种方式工作的原因是因为java脚本使用52+1位数字(基本格式章节下的表)。所以,在随机函数返回太大的值之后,它被舍入,例如
Math.pow(2, 54) +1
//18014398509481984
Math.pow(2, 54)
//18014398509481984
Math.pow(2, 54) -1
//18014398509481984
所有返回相同的值,该值被2除(因为四舍五入)
要了解更多信息,您可以播放并查看它在biniry格式中的外观,例如:
parseInt(Math.pow(2, 54) - 2).toString(2)
//"111111111111111111111111111111111111111111111111111110"
parseInt(Math.pow(2, 54) - 3).toString(2)
//"111111111111111111111111111111111111111111111111111100"
parseInt(Math.pow(2, 54) ).toString(2)
//"1000000000000000000000000000000000000000000000000000000"
parseInt(Math.pow(2, 54) -1).toString(2)
//"1000000000000000000000000000000000000000000000000000000"
之所以会出现偏差,是因为Math.random()
的结果并不总是具有相同的长度,因此,例如0.123
和0.1235
计入“一”堆
你可以认为如果你用尾随的零来平衡长度,它会被修正,但这也不正确,因为0.123
可能是一个四舍五入的0.1229999999
第一种方法的实际错误取决于不精确分数中的最低有效位(%2和%5都只受最后一位的影响),在从二进制转换为十进制表示时,该分数会出现舍入错误
分数的原始二进制形式可能是均匀分布的,但在Javascript中无法读取它
现在,如果有人能解释一个四舍五入的小数的尾随数字的分布…有些事情让我觉得这是因为你在增加模数之前的数字的大小,但我想不出为什么。这可能与Number()
如何格式化输出有关。不过。如果没有*10000
,两者之间是否一致?@Askanison4我希望我能同意(或反驳!),但我自己也感到困惑,办公室里的人对此有点疯狂:D@Askanison4如果我不乘,就不能模化,但如果我只乘以100,结果仍然是一样的。Javascript实际上偏向于偶数“JavaScript中的数字是IEEE 754浮点数字,具有舍入到最近的偶数行为”是的,这与舍入有关在第一种方法中切掉最后的数字效果很好,但我不确定这是如何解释结果的一致性的——对于任何数量的NUM\u of_POSSIBLES
@MeLight——偏倚解释了2和5的结果。我看不到其他许多可能值的偏差(例如3或7)。我怀疑因子为2或5的NUM\u of_POSSIBLES
的值将显示randomA
的偏差,因为JavaScript生成表示的最后一个数字时存在偏差。