我想证明一个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#。


当前回答

当然guid也会发生碰撞。由于guid是128位的,只需生成其中的2^128 + 1个,根据鸽子洞原理,肯定会有碰撞。

但是当我们说一个GUID是唯一的时,我们真正的意思是键空间非常大,实际上不可能意外地生成两次相同的GUID(假设我们是随机生成GUID)。

如果随机生成n个guid序列,那么至少发生一次碰撞的概率大约是p(n) = 1 - exp(-n^2 / 2 * 2^128)(这是一个生日问题,可能的生日数量为2^128)。

   n     p(n)
2^30 1.69e-21
2^40 1.77e-15
2^50 1.86e-10
2^60 1.95e-03

为了使这些数字具体化,2^60 = 1.15e+18。所以,如果你每秒生成10亿个guid,你将需要36年才能生成2^60个随机guid,即使这样,你发生碰撞的概率仍然是1.95e-03。在接下来的36年里,你更有可能在生命中的某个时刻被谋杀(4.76e-03),而不是发现一次碰撞。祝你好运。

其他回答

你们都没抓住重点吗?

我认为guid是用两个东西生成的,这使得它们具有全局唯一性的几率相当高。一是它们以你所在机器的MAC地址作为种子,二是它们使用生成它们的时间加上一个随机数。

因此,除非您在实际的机器上运行它,并在机器用来表示GUID中的时间的最短时间内运行您的所有猜测,否则无论您使用系统调用进行多少次猜测,都不会生成相同的数字。

我想如果您知道GUID的实际生成方式,实际上会大大缩短猜测的时间。

Tony

Go to the cryogenics lab in the New York City. Freeze yourself for (roughly) 1990 years. Get a job at Planet Express. Buy a brand-new CPU. Build a computer, run the program, and place it in the safe place with an pseudo-perpetual motion machine like the doomsday machine. Wait until the time machine is invented. Jump to the future using the time machine. If you bought 1YHz 128bit CPU, go to 3,938,453,320 days 20 hours 15 minutes 38 seconds 463 ms 463 μs 374 ns 607 ps after when you started to run the program. ...? PROFIT!!!

... 即使你的1YHz CPU是1GHz CPU的1,000,000,000,000,000倍(如果你更喜欢使用二进制前缀,则为1,125,899,906,842,624倍),也至少需要10,783,127年。

因此,与其等着计算结束,不如去喂那些因为其他n只鸽子夺走了它们的家而失去家园的鸽子。:(

或者,你可以等到128位量子计算机被发明出来。然后,您可以通过在合理的时间内(可能)使用您的程序来证明GUID不是唯一的。

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

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

如果你想在代码的许多地方检查guid的唯一性,你可以使用一个漂亮的小扩展方法。

internal static class GuidExt
{
    public static bool IsUnique(this Guid guid)
    {
        while (guid != Guid.NewGuid())
        { }
        return false;
    }
}

要调用它,只需调用Guid。每当你生成一个新的guid…

Guid g = Guid.NewGuid();
if (!g.IsUnique())
{
    throw new GuidIsNotUniqueException();
}

...见鬼,我甚至建议打电话两次,以确保它在第一轮就得到了正确的答案。

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

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

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

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