我正在使用
var crypto = require('crypto');
var uid = crypto.pseudoRandomBytes(8);
生成64位ID。
我不需要这些是真正随机的,但我希望它们在0
和ffffffffffffffff
之间均匀分布。但是,他们不是。以这种方式生成1,000,000个64位整数:
var bignum = require('bignum');
var crypto = require('crypto');
var randomBignum = function() {
return bignum.fromBuffer(crypto.pseudoRandomBytes(8));
}
var avg = randomBignum();
var avg_len = avg.bitLength();
var lengths = {};
for (var i = 0; i < 1e6; i++) {
var big = randomBignum();
avg = avg.add(big).div(2);
var length = big.bitLength();
if (typeof lengths[length] === 'undefined') { lengths[length] = 0; }
lengths[length] += 1;
avg_len = (avg_len + length) / 2;
}
console.log('Average integer: %s', avg);
console.log('Average bit length: %s', avg_len);
console.info('Bit length distribution: %s', require('util').inspect(lengths));
产生
Average integer: 8386866841744540769
Average bit length: 63.11672078688376
Bit length distribution: {
'45': 1,
'47': 2,
'48': 7,
'49': 15,
'50': 23,
'51': 66,
'52': 114,
'53': 248,
'54': 521,
'55': 955,
'56': 1905,
'57': 4019,
'58': 7742,
'59': 15552,
'60': 31396,
'61': 63048,
'62': 125182,
'63': 249271,
'64': 499933 }
我可能会对这里的统计数据感到困惑,但这些数据并不是均匀分布的,对吧?每个字节单独随机生成的事实使得不可能生成连续的0字节,因此您的小数字会少得多。
在Node中生成统一分布的64位ID有什么好方法?我应该使用Math.random
并将结果乘以ffffffffffffffff
吗?
答案 0 :(得分:3)
他们(可能)是制服!获得0的概率与获得18446744073709551615的概率相同,但在该范围内有4611686018427387904个数字没有前导零,只有一个有64个。您应该期望看到每个位数大约是前一个位数的两倍,您的测试同意这一点。