用于生成唯一数字的C#逐位操作
本文关键字:位操作 数字 唯一 用于 | 更新日期: 2023-09-27 18:29:25
我正试图借助DateTime记号和递增数字在c#中生成唯一值。伪代码:
- 从DateTime中取最后43个有效位。现在打勾(将其命名为A)
- 从递增序列中取最后21位(将其命名为"B")
- 左移"A"21次(将其命名为"C")
- 在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"。
欢迎任何帮助/建议/改进。
这个逻辑是否足以生成唯一的数字
在什么范围内独一无二?跨多台计算机/进程/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",则该数字将变为负数。没什么好担心的。