【发布时间】:2014-11-12 08:34:09
【问题描述】:
我很好奇 NaN 在 IEEE 单精度和双精度浮点中的实现和表示,我发现 this implementation 是一个“is 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)或者也许!= 比负或位移位要慢。否则,我难住了。
作为参考,我用来尝试所有整数的代码,以防出错。
#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;
}
【问题讨论】:
-
分别打印出
lx和-lx的位模式,看看你会发现什么。 -
移除条件跳转。
-
Joachim,现在我看到了结果,我明白为什么它只有 1 比 0,因为如果它不为零,那么
lx或 @ 的最高有效位(符号位) 987654332@ 将是 1(因此当您向右位移 31 位时,它将是 1)。我的问题是为什么不使用(lx != 0)而不是比较。 -
Michael,据我了解,如果指数位全为 1 且有效位/尾数位全为 0,则浮点数为
NaN。我试图解开那个表达式的奥秘时遇到了障碍,所以我没有太深入地研究函数的其余部分,但我的直觉说它应该起作用。由于双精度的低 32 位都是有效数的一部分,我相信如果低位中有任何非零位,我认为这个想法是在高位 int32 的末尾放置一个 1 (因此,与0) 然后从上半部分开始检查有效位中的任何 1。 -
@Jengerer:谢谢 - 我不确定在我之前尝试解决代码正在做什么时我做错了什么,但你已经击中了它(除了 NaN尾数非零;如果尾数全为零,则表示无穷大)。这再次证明我应该始终避免处理浮点问题。
标签: c integer bitwise-or