如何根据GUID生成唯一的整数

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

int i = Guid.NewGuid().GetHashCode(); int j = BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0); 

哪一个更好?

Eric Lippert做了一个非常有趣的(一如既往)关于哈希碰撞概率的文章。

你应该读一遍,但他用这个非常说明性的图表来结束:

散列冲突的概率

与你的具体问题相关,我也将使用GetHashCode因为碰撞将是不可避免的。

GetHashCode函数是专门devise用于创build一个分布良好的整数范围,具有较低的碰撞概率,所以对于这个用例来说可能是最好的。

但是,正如我确信你知道的那样,将128位信息散列成32位信息会丢失大量数据,所以如果有足够多的GUID,几乎肯定会发生冲突。

这是最简单的方法:

 Guid guid = Guid.NewGuid(); Random random = new Random(); int i = random.Next(); 

你会注意到guid实际上并没有在这里使用,主要是因为使用guid没有意义。 微软的GUIDalgorithm不再使用计算机的MAC地址 – GUID实际上是使用一个伪随机生成器(基于时间值)生成的,所以如果你想要一个随机整数,使用Random类更有意义。

更新:实际上,使用一个GUID生成一个int可能会比仅仅使用Random更糟糕(更糟的是,这将更有可能产生冲突)。 这是因为GUID中不是全部128位都是随机的。 理想情况下,你会想要从散列函数中排除不变的位,尽pipe如前所述,生成一个随机数会容易得多。 🙂

一个GUID是一个128位的整数(它只是hex而不是十进制)。 与.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) 

如果你没有.NET 4,你可以看看IntX或Solver Foundation 。

由于GUID空间大于32位整数的数量,因此如果您有足够的GUID,就可以保证有冲突。 鉴于你的理解,并准备处理碰撞,但是很less,GetHashCode()是专门为此目的而devise的,应该是首选。

在静态类中,保留一个静态常量整数,然后在每次访问(使用public get属性)之前加1。 这将确保您在获取非唯一值之前循环整个范围。

  /// <summary> /// The command id to use. This is a thread-safe id, that is unique over the lifetime of the process. It changes /// at each access. /// </summary> internal static int NextCommandId { get { return _nextCommandId++; } } private static int _nextCommandId = 0; 

这将在正在运行的进程中产生一个唯一的整数值。 既然你没有明确定义你的整数应该是多less,这可能会适合。

如果你想突破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; } 

在遇到碰撞之前,宇宙将衰退到一个寒冷而黑暗的空间。

也许不是整数,而是小的唯一键,无论如何短于GUID:

http://www.codeproject.com/Articles/14403/Generating-Uni​​que-Keys-in-Net

我需要一个控制台应用程序的多个实例需要获得一个唯一的整数ID。 它用于标识实例并在启动时分配。 因为.exe是用手启动的,所以我使用开始时间的刻度来解决一个解决scheme。

我的推理是用户几乎不可能在同一毫秒内启动两个.exe文件。 这种行为是确定性的:如果碰撞,你就知道问题是两个实例同时启动。 取决于哈希码,GUID或随机数的方法可能以不可预知的方式失败。

我将date设置为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); 

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

  • 这些实例是手动启动的(超过一毫秒)
  • ID在启动时每个实例生成一次
  • 对于当前正在运行的其他实例,ID只能是唯一的
  • 将只需要less量的ID