我使用SecureRandom.urlsafe_base64(8)
是为了在我的系统中创建URL安全的唯一id。
我想知道如何计算碰撞的概率?我要在数组中插入10000个这样的id,我想避免检查其中一个键是否已经在数组中,但我也想确保它们不会重复?这种可能性有多大?
这个概率有一个很好的近似值(它与生日问题有关)。若存在k
电位值,且采样n
,则碰撞概率为:
k! / (k^n * (k - n)!)
base64方法返回一个基于输入的随机字节数而不是随机数字数构建的base64字符串。8个随机字节给我们k = 256^8
,大约是1.8446744e+19
。你要生成10000个这样的字符串,所以是n = 10,000
,这给了我们2.710498492319857e-12
的概率,这是非常低的。
你不能通过计算概率来确定某件事,你只能知道它发生的可能性。
为了保护自己,只需为数据库列添加唯一索引。这样可以确保不能在数据库中存储重复条目。有了这样一个唯一的索引,插入将引发一个ActiveRecord::InvalidStatement
错误,如果这种情况不太可能发生(参见@Andrew的回答)。
稍微调整一下Andrew的回答,我相信碰撞概率的公式是:
1 - (k! / (k^n * (k - n)!))
设k
为势值,n
为样本数。方程:
k! / (k^n * (k - n)!)
给出了不发生碰撞的概率——根据生日问题wiki。
您可以通过尝试几个不同的n
值来检查这一点。更多的样本自然会产生更高的碰撞概率。