问题描述
我对IEEE单精度和双精度浮点中 NaN
的实现和表示感到好奇,我找到了的是NaN功能。即:
I was curious about the implementation and representation of NaN
in both IEEE single- and double-precision floating points, and I found this implementation of an "is NaN" function. Namely:
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
,并且在我无法理解之后,我在所有整数上测试了它,并且发现它导致0为 lx = 0
而另外一个。
I didn't understand the purpose of (lx|(-lx)) >> 31
, and after failing to reason it out in my head, I tested it on all integers, and found it results in 0 for lx = 0
and 1 otherwise.
我想出的唯一理由是可能使用(lx!= 0)
相反是不可能的,因为某些C标准没有定义为真实操作分配的整数值(例如,不保证为1为真)或者可能!=
比负位移和位移位。否则,我很难过。
The only reasons I could come up with are that perhaps using (lx != 0)
instead was not possible due to some C standard not defining what integer value is assigned to true operations (e.g. not guaranteed to be 1 for true) or that perhaps !=
is slower than the negative-or-and-bit-shift. Otherwise, I'm stumped.
作为参考,我用来尝试所有整数的代码,如果有错误。
For reference, the code I used to try all integers, in case of errors.
#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
,你正在对目标代码强制执行分支操作。
However, with lx==0? 0:1
, you are imposing a branch operation into the object code.
与一些比特相比,这可能会降低性能明智的操作。
This might yield reduced performance in comparison with a couple of bit-wise operations.
这实际上取决于底层硬件架构以及手头的指定编译器。
It really depends on the underlying HW architecture as well as the designated compiler at hand.
但它肯定会导致不一致的性能,具体取决于分支预测启发式。
But it will for sure lead to inconsistent performance, depending on branch-prediction heuristics.
的运行时间( u_int32_t)(lx |(-lx))>>> 31
保证在每次执行时都相同。
The running time of (u_int32_t)(lx|(-lx))>>31
is guaranteed to be identical on every execution.
这篇关于整数及其负数的按位OR的目的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!