随机数生成器,我的方法/统计数据有什么问题? [JS]

时间:2015-02-27 18:25:47

标签: javascript random statistics sha512

首先,我想知道的是,如果我在做系统性的错误,或者我搞砸了数学,或者你有什么想法可能出错?

我正在尝试编写一个随机数生成器,这些数字可以被用户影响/验证(可证明是合理的)。生成的数字介于4096和65535之间。我模拟了100,000次函数并获得了一些奇怪的统计数据(或者我认为错了?)。 为什么这个数字在8000以下的概率大约为50%。在数字范围的中间(~30700),它不应该是50%吗?

以下是模拟的输出:

< 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生成的。)

让我的&#34;随机&#34;数字,我取两个(用户和服务器)哈希并将它们添加为十六进制数字(userhash + serverhash = result)。然后我取结果并切除除前4位数之外的所有内容。 (例如结果= CF27) 之后,我再次将其转换为十进制。

我可以得到的最小数字应该是Hex 1000(dec = 4096),Hex 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;
}

2 个答案:

答案 0 :(得分:1)

这是因为你得到的前四位数字会导致结果偏差。

对于50%的数字,您将获得65位数而不是64位的结果,第一位数字为1.例如,在示例中添加两个数字:

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

从结果中取前四位数字会得到10C0。从结果中可以看出,1000(4096)和1FFF(8191)之间有很多数字。其中大多数是数字,其结果是65位而不是64位。

如果您改为在特定位置(右侧的计数器)取任何四位数字,例如最后四位数字,您将在0000FFFF之间获得非常均匀的数字分布。

答案 1 :(得分:0)

您设计的简化版本:

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的第一个数字。