生成64位整数的均匀分布

时间:2014-07-15 20:13:33

标签: javascript node.js random statistics

我正在使用

var crypto = require('crypto');
var uid = crypto.pseudoRandomBytes(8);

生成64位ID。

我不需要这些是真正随机的,但我希望它们在0ffffffffffffffff之间均匀分布。但是,他们不是。以这种方式生成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吗?

1 个答案:

答案 0 :(得分:3)

他们(可能)制服!获得0的概率与获得18446744073709551615的概率相同,但在该范围内有4611686018427387904个数字没有前导零,只有一个有64个。您应该期望看到每个位数大约是前一个位数的两倍,您的测试同意这一点。