使用 Math.random 获得相同值的概率

Probability of getting the same value using Math.random

要求是当用户点击提交按钮时向数据库发送一个唯一的 ID。所以我使用 Javascript Math.random 方法。我只想知道获得相同数字的机会或可能性是多少,以及使用 Math.random.

的位数是多少

我更喜欢使用时间戳、客户端或用户相关标识符生成的我自己的随机数。

不要这样做。相信(多个)客户提出独特的价值是行不通的。

即使保证每个客户端生成唯一值,您也可以让两个客户端生成相同的值。由于大多数伪随机数生成器都以当前时间为种子,因此随着用户的增加,这种情况变得更有可能。

如果您要创建数据库记录,您的数据库应该提供这样的一些功能。大多数或所有 SQL 数据库都有一个自动递增的概念,许多 NoSQL 数据库都有一个等价的概念(Mongo 肯定有 ID)。让数据库来处理这对性能有好处(它可以设置索引并分配space来很好地处理ID)并且DB对数据有最终决定权,因此它可以保证ID是唯一的。

否则,您可以让服务器端生成一些唯一标识符(如 UUID)并使用它。让服务器执行此操作并使用已知良好的算法(如类型 4 UUID)可确保足够的随机性,从而避免发生冲突。请注意,除非您的数据库具有适用于它们的类型,否则使用 UUID 将具有与顺序 ID 截然不同的索引性能。

你遇到了一个叫做生日问题的问题:即使有 366 种可能的生日,当你在一个房间里只有 26 个人时,一些人生日相同的可能性要高于 50-50 .通常,当您的数字接近样本量的平方根时(26 在 366 的平方根附近),很可能会发生冲突。

Javascript 的 Math.random() 具有大约 52 位的随机性。因此,当您的记录数接近 2**26(大约 6000 万条,对于数据库来说是一个相当适中的大小)时,应该很可能发生冲突。

您应该使用至少 128 位(最好是 256 位)的加密安全 PRNG,以避免冲突。可能有现成可用的 UUID 库。

对于给定数量的键 k 和键空间 N,碰撞的近似几率为:

1 - exp((-k * (k-1))/(2 * N))

所以对于 k=100 万条记录,N=2**52,如果我算对的话,这大约是 9000 分之一。这进一步假设 Javascript 的 Math.random() 确实使用了可用的填充 52 位随机性……这也是我不会做出的假设。