如何基于GUID生成唯一的整数

ano*_*nim 54 c#

是否有可能从GUID生成(极可能)唯一的整数?

int i = Guid.NewGuid().GetHashCode();

int j = BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0);
Run Code Online (Sandbox Code Playgroud)

哪一个更好?

Joã*_*elo 44

Eric Lippert做了一篇关于哈希冲突概率的非常有趣(一如既往)的帖子.

你应该阅读所有内容,但他总结了这个非常具有说明性的图形:

哈希冲突的可能性

与您的具体问题相关,我也会这样做,GetHashCode因为无论如何,碰撞都是不可避免的.

  • 即不要这样做. (19认同)

Gre*_*ech 18

GetHashCode功能专门设计用于创建分布均匀的整数范围,具有较低的碰撞概率,因此对于此用例可能是您可以做的最好的.

但是,正如我确信您所知,将128位信息散列到32位信息中会丢弃大量数据,因此如果您有足够多的GUID,几乎肯定会发生冲突.

  • 如果你将"足够大"大于2 ^ 32,你可以删除"几乎".在这种情况下,碰撞得到保证. (4认同)

Mus*_*sis 16

这是最简单的方法:

Guid guid = Guid.NewGuid();
Random random = new Random();
int i = random.Next();
Run Code Online (Sandbox Code Playgroud)

你会注意到guid这里实际上并没有使用它,主要是因为使用它没有意义.Microsoft的GUID算法不再使用计算机的MAC地址 - GUID实际上是使用伪随机生成器(基于时间值)生成的,因此如果您想要一个随机整数,那么使用Random该类更有意义.

更新: 实际上,使用GUID生成一个int可能比使用Random更糟糕("更糟糕",因为这更可能产生冲突).这是因为并非GUID中的所有128位都是随机的.理想情况下,您可能希望从散列函数中排除非变量位,尽管生成随机数会容易得多,正如我之前提到的那样.:)

  • 也许有一个很好的理由为什么OP想要从GUID派生整数. (7认同)
  • OP可能会认为*有一个很好的理由从GUID派生一个整数(即,为了确保int的唯一性),但确实没有. (4认同)
  • 仅为了便于阅读:79,228,162,514,264,337,593,543,950,336. (3认同)
  • 只是为了增加我的 2 美分......我们所有的键都是 GUID,我们正在调用的网络服务要求键是整数。因此,从 GUID 到整数的原因。 (3认同)

Jus*_*tin 13

GUID是128位整数(它只是十六进制而不是十进制).使用.NET 4,请使用http://msdn.microsoft.com/en-us/library/dd268285%28v=VS.100%29.aspx,如下所示:

// Turn a GUID into a string and strip out the '-' characters.
BigInteger huge = BigInteger.Parse(modifiedGuidString, NumberStyles.AllowHexSpecifier)
Run Code Online (Sandbox Code Playgroud)

如果您没有.NET 4,可以查看IntXSolver Foundation.

  • 这是有效的,虽然必须注意产生的数字是负面的,看看这个小提琴:https://dotnetfiddle.net/B97Fhv. (4认同)
  • 终于有实际答案了。 (2认同)

s2d*_*ker 7

如果您希望突破2 ^ 32障碍,请尝试以下方法:

/// <summary>
/// Generate a BigInteger given a Guid. Returns a number from 0 to 2^128
/// 0 to 340,282,366,920,938,463,463,374,607,431,768,211,456
/// </summary>
    public BigInteger GuidToBigInteger(Guid guid)
    {
        BigInteger l_retval = 0;
        byte[] ba = guid.ToByteArray();
        int i = ba.Count();
        foreach (byte b in ba)
        {
            l_retval += b * BigInteger.Pow(256, --i);
        }
        return l_retval;
    }
Run Code Online (Sandbox Code Playgroud)

在遇到碰撞之前,宇宙会衰变到寒冷和黑暗的地方.


Geo*_*der 6

我有一个要求,其中控制台应用程序的多个实例需要获得唯一的整数 ID。它用于标识实例并在启动时分配。由于 .exe 是手动启动的,因此我使用启动时间的刻度确定了解决方案。

我的理由是,用户几乎不可能在同一毫秒内启动两个 .exe。这种行为是确定性的:如果发生冲突,您就会知道问题在于同时启动了两个实例。依赖于哈希码、GUID 或随机数的方法可能会以不可预测的方式失败。

我将日期设置为 0001-01-01,添加当前时间并将刻度除以 10000(因为我没有设置微秒)以获得一个小到足以放入整数的数字。

 var now = DateTime.Now;
 var zeroDate = DateTime.MinValue.AddHours(now.Hour).AddMinutes(now.Minute).AddSeconds(now.Second).AddMilliseconds(now.Millisecond);
 int uniqueId = (int)(zeroDate.Ticks / 10000);
Run Code Online (Sandbox Code Playgroud)

编辑:有一些警告。为避免发生碰撞,请确保:

  • 实例手动启动(间隔超过一毫秒)
  • 每个实例在启动时生成一次 ID
  • ID 必须仅对于当前正在运行的其他实例是唯一的
  • 只需要少量的 ID


tva*_*son 5

因为GUID空间大于32位整数的数量,所以如果您有足够的GUID,就可以确保发生冲突。鉴于您已了解并且已准备好应对冲突(无论多么罕见),GetHashCode()正是为此目的而设计的,应该被首选。