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

ZeN*_*eNo 0 c# algorithm bit-manipulation unique c#-4.0

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

  1. 从DateTime.Now ticks(让我们命名为A)取最后43位有效位
  2. 从增加的序列中取最后21位(让它命名为'B')
  3. 左移'A'21次(让它命名为'C')
  4. 在A和C中做二进制OR

我运行测试以生成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;
        }
Run Code Online (Sandbox Code Playgroud)

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

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

Jon*_*eet 6

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

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

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

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

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

只要dateTimeNo设置了它的最高位(43位),你最终会得到一个long顶部位设置 - 这意味着它将是负数.

编辑:还要注意你的换档是坏的.这个:

const long dateTimeMask = ~(0L) >> timeShift;
Run Code Online (Sandbox Code Playgroud)

执行一个符号扩展的移位 - 所以你只是以〜0L结束.

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