首先,我想知道的是,如果我在做系统性的错误,或者我搞砸了数学,或者你有什么想法可能出错?
我正在尝试编写一个随机数生成器,这些数字可以被用户影响/验证(可证明是合理的)。生成的数字介于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;
}
答案 0 :(得分:1)
这是因为你得到的前四位数字会导致结果偏差。
对于50%的数字,您将获得65位数而不是64位的结果,第一位数字为1.例如,在示例中添加两个数字:
3CDC3C8C9...
CF27CC73E...
= 10C0409007...
从结果中取前四位数字会得到10C0
。从结果中可以看出,1000
(4096)和1FFF
(8191)之间有很多数字。其中大多数是数字,其结果是65位而不是64位。
如果您改为在特定位置(右侧的计数器)取任何四位数字,例如最后四位数字,您将在0000
和FFFF
之间获得非常均匀的数字分布。
答案 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的第一个数字。