随机数生成器,我的approach/statistics怎么了? [JS]

Random number generator, what's wrong with my approach/statistics? [JS]

首先,我想知道我是否犯了系统错误,或者我是否搞砸了数学,或者你有什么想法可能是错误的吗?

我正在尝试编写一个随机数生成器,用户可以影响/验证这些随机数(证明是公平的)。生成的数字在 4096 到 65535 之间。我模拟了该函数 100,000 次,得到了一些奇怪的统计数据(或者我想错了??)。 为什么这个数字低于 8000 的可能性约为 50%。它不应该是数字范围中间的 50% (~30700) 吗?

这是模拟的输出:

< 65536 : 100000 Times :100%
< 60000 : 91813 Times :91.813%
< 56000 : 86406 Times :86.406%
< 52000 : 81334 Times :81.334%
< 48000 : 76743 Times :76.743%
< 32768 : 62356 Times :62.356%
< 32000 : 61748 Times :61.748%
< 30719 : 60860 Times :60.86%
< 24000 : 56628 Times :56.628%
< 16000 : 52871 Times :52.871%
< 12000 : 51540 Times :51.54%
< 8000 : 50447 Times :50.447%
< 6000 : 36003 Times :36.003%
< 5096 : 21583 Times :21.583%
< 4608 : 11714 Times :11.714%
< 4250 : 3674 Times :3.674%
< 4100 : 100 Times :0.1%
< 4096 : 0 Times :0%

关于我写的函数的更多细节:

我正在生成两个散列。一个是 userhash,另一个是 serverhash。这两个都有格式,例如:

Server =3CDC3C8C97DEE62169B2C403BB2B6B501C1B0A0BD8015699B47DA67789C3F628
User   =CF27CC73E33E0AC1DA5239DE8DAF94044D89B8636DA90F4CE510E652C8AC7F54

(Userhash 由唯一 ID 生成。Serverhash 是通过获取随机数(标准函数:math.random() )和时间戳,然后对它们进行 HMAC-SHA-512 生成的。)

为了获得我的 "random" 号码,我采用了(用户和服务器)哈希并将它们添加为十六进制数字(userhash + serverhash = result)。然后我得到结果并删除除前 4 位数字之外的所有内容。 (例如结果 = CF27) 之后,我再次将其转换为十进制。

我能从中得到的最小数字应该是十六进制 1000 (dec=4096),最大的应该是十六进制 FFFF (dec=65535)。这意味着我的随机数应该在 4096 - 65535 的范围内。

代码片段:

//Function for getting a dec number from two hashes
function test_Rand(SERVER_SECRET, CLIENT_SECRET){

    var client_hash = require('crypto'),
        text = CLIENT_SECRET,
        key  = SERVER_SECRET

    // create hash
    var hash = client_hash.createHmac('sha512', key);
    hash.update(text);
    var clientRollAsHex = hash.digest('hex')
    var serverRollAsHex = SERVER_SECRET;
    //Add the numbers in Hex
    var roll_hex = addHex(clientRollAsHex, serverRollAsHex); 
    //Cut the hex String
    roll_hex = roll_hex.substring(0,4);
    // Make INT
    var roll_dec = parseInt(roll_hex, 16);
return roll_dec;

}

//Function for Hex-adding
function addHex(c1, c2) {
  var hexStr = (parseInt(c1, 16) + parseInt(c2, 16)).toString(16);
  while (hexStr.length < 6) { hexStr = '0' + hexStr; } // Zero pad.
  return hexStr;
}

SERVER_SECRET来自以下函数。

var secret = function() {
    var r1 = Math.random()*10000000 + Math.floor(Date.now() / 1000);
    var r2 = Math.random()*1000000 + Math.floor(Date.now() / 2000);   //That does not make much sense
    var new_hash = require('crypto');
    var text = r1;
    var key  = r2;

    // create hahs
    var r_hash = new_hash.createHmac('sha512', key.toString());
    r_hash.update(text.toString());
    var retrn = r_hash.digest('hex');

    return retrn;
}

您的设计的简化版本:

var a=Math.floor((Math.random() * 10));
var b=Math.floor((Math.random() * 10));

a+b的范围是多少? 0-18 现在只取结果的第一位数字。那么 0-9 仍然是它们的原始值 * 但 10-18 变为 1.

要获得您想要的结果,您需要删除第 10-18 种情况的第一个数字。

这是因为您取的是前四位数字,所以结果有偏差。

对于 50% 的数字,您将得到一个长度为 65 位而不是 64 位的结果,并且第一个数字是 1。例如,将您的示例中的两个数字相加:

   3CDC3C8C9...
   CF27CC73E...
= 10C0409007...

从结果中取出前四位数字得到 10C0。正如您从结果中看到的,1000 (4096) 和 1FFF (8191) 之间有很多数字。其中大部分是结果为 65 位而不是 64 位的数字。

如果您取而代之的是在特定位置(从右边算起)取任意四位数字,例如最后四位数字,您将在 0000 和 [=15= 之间获得相当均匀的数字分布].