我很好奇 NaN
在 IEEE 单精度和 double 浮点中的实现和表示,我发现了 this implementation一个“是 NaN”的函数。即:
int isnan(double x)
{
int32_t hx,lx;
// Move lower 32 bits of double to lx, higher 32 to hx.
EXTRACT_WORDS(hx,lx,x);
// Remove sign bit, since -NaN and NaN are both NaN.
hx &= 0x7fffffff;
// Equivalent to hx |= (lx != 0).
hx |= (u_int32_t)(lx|(-lx))>>31;
// Difference is negative iff (hx & 0x7ff00000) == 0x7ff00000 and (hx & 0x000fffff) != 0.
hx = 0x7ff00000 - hx;
return (int)((u_int32_t)(hx))>>31;
}
我不明白 (lx|(-lx)) >> 31
的目的,在我头脑中无法推理出来之后,我对所有整数进行了测试,发现lx = 0
结果为 0,否则为 1。
我能想到的唯一原因可能是使用 (lx != 0)
是不可能的,因为某些 C 标准没有定义分配给真正操作的整数值(例如,不是保证为 1 表示真)或者 !=
可能比 negative-or-and-bit-shift 慢。否则,我很难过。
作为引用,我用来尝试所有整数的代码,以防出现错误。
#include <stdio.h>
#include <stdint.h>
int main(void) {
int32_t i = 0;
do {
if (((uint32_t)(i | (-i)) >> 31) == 0)
printf("%d\n", i); // prints only 0
} while (i++ != 0xFFFFFFFF); // overflows to -max_int and then climb to -1
return 0;
}
最佳答案
表达式 (u_int32_t)(lx|(-lx))>>31
等价于 lx==0? 0:1
.
然而,对于 lx==0? 0:1
,您正在将分支操作强加到目标代码中。
与几个按位操作相比,这可能会降低性能。
这实际上取决于底层硬件架构以及手头指定的编译器。
但这肯定会导致性能不一致,具体取决于分支预测启发式方法。
(u_int32_t)(lx|(-lx))>>31
的运行时间在每次执行时保证相同。
关于c - 整数与其负数按位或的目的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25905263/