我想证明一个GUID在一个简单的测试程序中不是唯一的。 我原以为下面的代码会运行几个小时,但它不起作用。我该怎么做呢?

BigInteger begin = new BigInteger((long)0);
BigInteger end = new BigInteger("340282366920938463463374607431768211456",10);  //2^128
for(begin; begin<end; begin++)
  Console.WriteLine(System.Guid.NewGuid().ToString());

我用的是c#。


当前回答

但你必须确保你有一个副本,还是你只关心是否有一个副本。为了确保有两个人生日相同,你需要366个人(不包括闰年)。如果有超过50%的概率有两个人同一天生日,你只需要23个人。这就是生日问题。

如果你有32位,你只需要77163个值就有超过50%的重复几率。试试吧:

Random baseRandom = new Random(0);

int DuplicateIntegerTest(int interations)
{
    Random r = new Random(baseRandom.Next());
    int[] ints = new int[interations];
    for (int i = 0; i < ints.Length; i++)
    {
        ints[i] = r.Next();
    }
    Array.Sort(ints);
    for (int i = 1; i < ints.Length; i++)
    {
        if (ints[i] == ints[i - 1])
            return 1;
    }
    return 0;
}

void DoTest()
{
    baseRandom = new Random(0);
    int count = 0;
    int duplicates = 0;
    for (int i = 0; i < 1000; i++)
    {
        count++;
        duplicates += DuplicateIntegerTest(77163);
    }
    Console.WriteLine("{0} iterations had {1} with duplicates", count, duplicates);
}

1000 iterations had 737 with duplicates

现在128位已经很多了,所以你仍然在谈论大量的物品,但碰撞的几率很低。对于给定的概率,您需要使用近似值获得以下记录数:

碰撞发生的概率是1/1000 217亿亿亿,50%的几率发生碰撞 396亿亿,90%的碰撞概率

每年大约发送1E14封电子邮件,所以在这个水平上大约需要40万年,你才能有90%的机会拥有两个具有相同GUID的电子邮件,但这与说你需要运行宇宙年龄830亿倍的计算机或太阳变冷才能找到副本有很大不同。

其他回答

任何两个guid都很可能是唯一的(不相等)。

看看这个SO条目,来自维基百科

而每个生成的GUID不是 保证是唯一的,总数 唯一键数(2^128或 3.4×10^38)是如此之大,以至于相同数字的概率为 生成两次是非常小的。为 例子,考虑可观测 宇宙,其中包含约5×10^22 星星;每颗恒星都有可能 6.8×10^15个通用唯一的guid。

所以你可能还要再等几十亿年,希望在我们所知道的宇宙结束之前,你能击中一个。

GUID理论上是非唯一的。下面是你的证明:

GUID是一个128位的数字 如果不重用旧的guid,就不能生成2^128 + 1或更多的guid

然而,如果太阳的全部能量输出都用于完成这一任务,那么它在完成之前就会变冷。

GUID可以使用许多不同的策略生成,其中一些策略采取特殊措施来确保给定的机器不会两次生成相同的GUID。在特定算法中发现冲突将表明生成guid的特定方法不好,但不能证明关于guid的任何一般情况。

你可以散列guid。这样,你就能更快地得到结果。

哦,当然,同时运行多个线程也是一个好主意,这样可以增加竞态条件在不同线程上两次生成相同GUID的机会。

由于部分Guid生成是基于当前机器的时间,我的理论是获得一个副本Guid:

重新安装Windows 创建一个启动脚本,在Windows启动时将时间重置为2010-01-01 12:00:00。 就在启动脚本之后,它触发应用程序生成一个Guid。 克隆此Windows安装,以便排除后续启动过程中可能出现的任何细微差异。 用此映像重新映像硬盘驱动器,并启动几次机器。

如果你担心独特性,你可以购买新的guid,这样你就可以扔掉旧的guid。如果你愿意,我可以把一些放在易趣网上。