如何根据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-Unique-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