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

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

本文关键字:有问题 统计数据 JS 方法 what 我的 随机数生成器      更新时间:2023-09-26

首先,我想知道的是,我是在犯系统性错误,还是数学搞砸了,或者你知道可能出了什么问题吗?

我试图编写一个小的随机数生成器,用户可以影响/验证这些数字(可以证明是公平的)。生成的数字介于4096和65535之间。我模拟了这个函数100000次,得到了一些奇怪的统计数据(或者我想错了??)。为什么这个数字低于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来生成的。)

为了得到我的"随机"数字,我同时使用(用户和服务器)散列,并将它们作为十六进制数字相加(userhash+serverhash=result)。然后我取结果,去掉除前4位数字以外的所有数字。(E.g结果=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;
}

这是因为你取前四位,所以你得到了一个偏斜的结果。

对于50%的数字,你会得到一个65位而不是64位的结果,第一位是1。例如,在您的示例中添加两个数字:

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

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

如果你在一个特定的位置(右边的计数器)取任意四位数字,例如最后四位,你会得到0000FFFF之间相当均匀的数字分布。

设计的简化版本:

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种情况下的第一个数字。