我很好奇NaN
在IEEE单精度和双精度浮点中的实现和表示,我发现{是3N}的“是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
我能想到的唯一原因是,由于某些C标准未定义为真实操作分配的整数值(例如,不保证为1表示真实),或许使用(lx != 0)
代替不可能或许!=
比负位移位慢。否则,我很难过。
作为参考,我用以尝试所有整数的代码,如果有错误。
#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;
}
答案 0 :(得分:3)
表达式(u_int32_t)(lx|(-lx))>>31
相当于lx==0? 0:1
。
但是,对于lx==0? 0:1
,您要对目标代码强制执行分支操作。
与一些按位操作相比,这可能会降低性能。
这实际上取决于底层的HW架构以及手头的指定编译器。
但它肯定会导致不一致的性能,具体取决于分支预测启发式。
(u_int32_t)(lx|(-lx))>>31
的运行时间保证在每次执行时都相同。