Joh*_*den 8 c math unsigned signed
我有一个来自无符号48位纳秒计数器的两个值,它可能会换行.
我需要两倍的差异,以纳秒为单位.
我想我可以假设读数是在大致相同的时间进行的,所以对于两个可能的答案,我认为我是最安全的.
他们都存储为uint64_t
.因为我认为我不能拥有48位类型.
我想计算它们之间的差异,作为有符号整数(大概int64_t
),考虑包装.
所以,例如,如果我开始
x=5
y=3
Run Code Online (Sandbox Code Playgroud)
然后结果x-y
是2
,并且如果我增加两个,x
并且y
即使它们包裹在最大值的顶部时也会保持这样0xffffffffffff
类似地,如果x = 3,y = 5,那么xy是-2,并且每当x和y同时递增时将保持不变.
如果我可以宣布x
,y
作为uint48_t
和差异int48_t
,我想
int48_t diff = x - y;
Run Code Online (Sandbox Code Playgroud)
会工作的.
如何使用我可用的64位算法模拟此行为?
(我认为任何可能运行的计算机都会使用2的补码算法)
PS我可能会破解这个,但我想知道是否有一个很好的标准方法来做这种事情,下一个阅读我的代码的人将能够理解.
PPS此外,这段代码最终会出现在最严格的紧密循环中,所以有效编译的东西会很好,所以如果必须有选择,速度就会超过可读性.
您可以通过uint64_t
在任何算术运算之后屏蔽a的前16位来模拟48位无符号整数类型.因此,举例来说,为了获得这两次之间的差异,您可以:
uint64_t diff = (after - before) & 0xffffffffffff;
Run Code Online (Sandbox Code Playgroud)
即使计数器在程序中缠绕,您也会得到正确的值.如果计数器没有环绕,则不需要屏蔽但也不会有害.
现在,如果您希望编译器将此差异识别为有符号整数,则必须对第48位进行符号扩展.这意味着如果设置了第48位,则该数字为负,并且您要设置64位整数的第49位到第64位.我认为一个简单的方法是:
int64_t diff_signed = (int64_t)(diff << 16) >> 16;
Run Code Online (Sandbox Code Playgroud)
警告:您应该测试这一点以确保它有效,并且当我将其转换uint64_t
为a时int64_t
,请注意存在实现定义的行为,并且当我将有符号的负数转移到右侧时,我认为存在实现定义的行为.我确信一位C语言律师能够提供一些更强大的东西.
更新: OP指出,如果您结合使用差异和执行符号扩展的操作,则不需要屏蔽.这看起来像这样:
int64_t diff = (int64_t)(x - y) << 16 >> 16;
Run Code Online (Sandbox Code Playgroud)