用于生成唯一编号的C#按位操作

时间:2012-03-28 06:22:56

标签: c# algorithm c#-4.0 unique bit-manipulation

我试图在DateTime滴答和增加数字的帮助下在c#中生成唯一值。 伪代码:

  1. 从DateTime.Now ticks(让我们命名为A)
  2. 取最后43位有效位
  3. 从递增序列中取出最后21位(将其命名为'B')
  4. 左移'A'21次(让它命名为'C')
  5. 在A和C中执行二进制OR
  6. 我运行测试以生成200万个数字并插入具有唯一约束集的数据库列并且它成功运行。

    以下是执行此操作的代码:

        private static long _sequence = 1;
        public static long GetUniqueNumber()
            {
                const int timeShift = 21;            
                var dateTime = DateTime.Now.Ticks;
                const long dateTimeMask = ~(0L) >> timeShift; 
                const long sequenceMask = ((~(0L) >> (64 - timeShift))); 
                var seq = Interlocked.Increment(ref _sequence);
                var dateTimeNo = (dateTimeMask & dateTime) << timeShift;
                var seqNum = (seq & sequenceMask);    
                var num = dateTimeNo | seqNum;
                return num;
            }
    

    我有两个问题: 这个逻辑是否足以产生唯一数字? 2.我发现一些生成的数字是'-ve',我不明白。

    欢迎任何帮助/建议/改进。

2 个答案:

答案 0 :(得分:6)

  

这个逻辑是否足以产生唯一数字

在什么范围内有独特之处?跨多个计算机/进程/ AppDomain s?当然不是。在一个AppDomain内?并不是的。生成200万个数字是无关紧要的 - 那就是只是测试你的序列部分是否有效。 (2 21 刚刚超过200万。)

如果您可以在GetUniqueNumber(可能是~10-15ms)的粒度内拨打DateTime.Now 2 21 +1次,那么您将得到一个重复。你有没有测量过你的计算机可以称之为多快?

然后有这样的事实:这些43位将在2 43 ticks'时间重复......或者至少如果你有一个足够细粒度的时钟。 (迟早,粒度会对你不利。)

  

我发现有些生成的数字是'-ve',我不明白。

每当dateTimeNo设置了最高位(43位)时,您最终会设置一个long并设置最高位 - 这意味着它将为负数。

编辑:还要注意你的换档是坏的。这样:

const long dateTimeMask = ~(0L) >> timeShift;

执行符号扩展转换 - 所以你最终只能得到~0L。

简而言之:使用Guid.NewGuid。这就是它的用途。

答案 1 :(得分:0)

负数是由于长期实施。由于它是带符号的数字,如果在位操作之后位64的MSB变为'1',则该数字将变为负数。没什么可担心的。