生成和连接3个Math.random()值比1 Math.random()值更随机吗?

时间:2016-07-06 15:45:27

标签: javascript random

我需要在更长的叙述中为多个句子生成唯一的id(多个用户可以在不同的机器上同时执行相同的操作)。

我考虑过做new Date().getTime()(也许连接一个username)但是因为id在循环中生成,同时迭代句子,我发现重复创建了(因为生成可以发生在同一毫秒)。

所以我现在正在玩:

var random1 = Math.floor((Math.random() * 10000) + 1).toString(36);
var random2 = Math.floor((Math.random() * 10000) + 1);
var random3 = Math.floor((Math.random() * 10000) + 1);
var id = random1 + random2 + random3;
// generates things like:  
// 1h754278042
// 58o83798349
// 3ls28055962

虽然我想到了(不可否认,作为一个没有考虑过独特/随机/加密问题的人),或许加入三个随机数并不是随机的一个随机数?

生成并连接3个Math.random()值比1 Math.random()值更随机吗?

这个答案(https://security.stackexchange.com/a/124003)说明:

  

如果随机生成器确实产生随机数据,那么它就不会   物质

但我不确定这对Math.random()的用法有何影响。

修改

场景是网络上的客户端而不是安全性,只是为了确保每个句子在数据库中都有唯一的ID。

修改

我最终实施了:

function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4();
}

var id = guid();

来自:https://stackoverflow.com/a/105074/1063287

另见答案评论:

  

实际上,RFC允许从随机创建的UUID   数字。你只需要旋转几个位来识别它   这样。见4.4节。从真实创建UUID的算法   随机或伪随机数:rfc-archive.org/getrfc.php?rfc=4122

3 个答案:

答案 0 :(得分:2)

通过连接3个均匀分布的随机字符串,您唯一可以改变的是更大范围的可能值。分布仍然是统一的,所以它不再是随机的"但它确实可以显着降低碰撞风险。那么可能值的数量将是36 ^ 12,或4.7383813e + 18。

通过连接12个base-36数字(0-9,A-Z)可以获得相同的效果。

答案 1 :(得分:1)

Math.random()返回一个带有正号的数字值,大于或等于0但小于1,使用依赖于实现的算法或策略随机或伪随机选择,在该范围内具有近似均匀的分布。 / p>

这是V8的实施:

d = {'ABC': [ "ASD"], 'DEF': ["AFS", "UAP"]}

来源:http://dl.packetstormsecurity.net/papers/general/Google_Chrome_3.0_Beta_Math.random_vulnerability.pdf

换句话说,3个随机值并不比1更“随机”。

答案 2 :(得分:0)

这太复杂了。

由于您使用随机数生成器的特定方式,第一个字符串可能相同而第二个或第三个字符串不同。这意味着您只需调用一次Math.random()即可生成更多唯一字符串。更多独特的字符串意味着更少的碰撞,这正是您的目标。

要确认这一点,只需将大量这些字符串转储到文件中,然后对它们进行排序,看看第二个和第三个值是否总是随第一个值改变,或者它们是否可以独立更改(您需要添加)分隔符到输出看到)。

这是PRNG状态隐藏方式的人工制品;经过一些追加后,它将停止工作。它应该(不保证!)经过这么多次迭代后,你不能轻易地测试它,所以不要尝试凭经验来解决它。

如果您有一个非常原始的生成器算法,那么您可能会发现只要random1等于X,那么random2总是等于Y而random3总是等于Z者除外;因此,如果你在X处发生了碰撞,那么隐含的Y和Z也会发生碰撞,因此他们无法提供帮助。

但是大多数PRNG(以及代码的结构,因为每次调用仅获取10000个不同的值),其状态远大于它们在单个调用中显示的状态。这意味着,即使random1为X,random2random3仍然完全不可预测,并且碰撞的可能性也会降低。

然而,当你到达random100时,你应该开始看到你可以根据所有其他randomX的值来猜测它将会是什么不会让字符串变得更独特。

然后整个问题在种子质量和状态大小的兔子洞中流下来。基本上,随机数生成器如此弱,以至于它只能生成少至40亿个唯一字符串,而在实际情况下可能会少得多,这似乎是合理的。 random()功能并不是为了解决GUID问题,因此存在一个很大的风险,即它会失败。