用于生成唯一数字的C#逐位操作

本文关键字:位操作 数字 唯一 用于 | 更新日期: 2023-09-27 18:29:25

我正试图借助DateTime记号和递增数字在c#中生成唯一值。伪代码:

  1. 从DateTime中取最后43个有效位。现在打勾(将其命名为A)
  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;
        }

我有两个问题:1.这种逻辑是否足以生成唯一的数字?2.我发现一些生成的数字是我不理解的"-ve"。

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

用于生成唯一数字的C#逐位操作

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

在什么范围内独一无二?跨多台计算机/进程/AppDomain s?,当然不是。在单个AppDomain内?不是。生成200万个数字是无关紧要的——这只是测试序列部分是否工作。(221刚刚超过200万。)

如果您可以在DateTime.Now的粒度内调用GetUniqueNumber 221+1次(可能为10-15ms),那么您将得到一个重复。你测量过你的计算机能以多快的速度调用这个吗?

然后,这43位将在243的时间内重复。。。或者至少如果你有一个足够细粒度的时钟。(粒度迟早会对你不利。)

我发现一些生成的数字是我不理解的"-ve"。

每当dateTimeNo的顶部比特(43个中)被设置时,您最终会得到一个顶部比特被设置的long,这意味着它将是负的。

编辑:还要注意你的换档坏了。此:

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

执行符号扩展移位-所以你只会得到~0L。

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

负数是由于long的实现。由于它是一个有符号的数字,如果位64的MSB在逐位操作后变为"1",则该数字将变为负数。没什么好担心的。