我在尝试在JavaScript中实现UUID生成器时遇到了一个有趣的现象。
基本上,在Node 4.2.2
上,如果使用内置的Math.random()
生成大量随机数:
var records = {};
var l;
for (var i=0; i < 1e6; i += 1) {
l = String(Math.random()).length;
if (records[l]) {
records[l] += 1;
} else {
records[l] = 1;
}
}
console.log(records);
数字的位数有一个奇怪的模式:
{ '12': 1,
'13': 11,
'14': 65,
'15': 663,
'16': 6619,
'17': 66378,
'18': 611441,
'19': 281175,
'20': 30379,
'21': 2939,
'22': 282,
'23': 44,
'24': 3 }
我本以为这是 V8 的随机数生成器的一个怪癖,但类似的模式也出现在 Python 3.4.3
中:
12 : 2
13 : 5
14 : 64
15 : 672
16 : 6736
17 : 66861
18 : 610907
19 : 280945
20 : 30455
21 : 3129
22 : 224
而Python代码如下:
import random
random.seed()
records = {}
for i in range(0, 1000000):
n = random.random()
l = len(str(n))
try:
records[l] += 1
except KeyError:
records[l] = 1;
for i in sorted(records):
print(i, ':', records[i])
这是预期的18位数及以下的模式:例如随机数应该有20位数字,如果一个数的最后一位是0,那么它实际上只有19位数字。如果随机数生成器很好,那么它发生的概率大约是1/10。
但是为什么19位及以上的模式相反呢?
我猜这与浮点数的二进制表示有关,但我无法确定原因。
__import__('collections').Counter(len(str(__import__('random').random())) for i in range(0, 1000000))
。 - Remi GuanMath.random().toString(2).length
,你会看到一个不同的模式,可能更符合你的期望。 - Jaromanda XArray.apply(null, Array(1e5)).map(() => Math.random()).reduce((records, n) => records[String(n).length] ? (records[String(n).length] += 1, records) : (records[String(n).length] = 1, records), {})
- Andreas Blaesus