[英]Why does the function work with float properly but doesn't work with double?
I found the code that checks whether a float is a power of 2: 我找到了检查浮点数是否为2的幂的代码:
int isPowOf2(float number) {
union {
float floatRepresent;
int intRepresent;
} bitset;
bitset.floatRepresent = number;
if((bitset.intRepresent & ((1 << 23)-1)) != 0)
return ((bitset.intRepresent & (bitset.intRepresent-1)) == 0); // denormalized number
int power = bitset.intRepresent >> 23;
return power > 0 && power < 255;
}
// ...
printf("[%f -> %d] ",2.0,isPowOf2(2.0f)); // [2.000000 -> 1]
printf("[%f -> %d] ",4.0,isPowOf2(4.0f)); // [4.000000 -> 1]
printf("[%f -> %d] ",0.25,isPowOf2(0.25f)); // [0.250000 -> 1]
printf("[%f -> %d]\n ",11.0,isPowOf2(11.0f)); // [11.000000 -> 0]
It works without issues as you can see in comments. 正如您在评论中看到的那样,它可以正常工作。 But when I try to turn this program into the version for double numbers, it gives wrong results:
但是,当我尝试将此程序转换为双倍数版本时,它给出了错误的结果:
int isPowOf2(double number) {
union {
double floatRepresent;
long long intRepresent;
} bitset;
bitset.floatRepresent = number;
if((bitset.intRepresent & ((1 << 53)-1)) != 0)
return ((bitset.intRepresent & (bitset.intRepresent-1)) == 0); // denormalized number
int power = bitset.intRepresent >> 53;
return power > 0 && power < 2047;
}
// ...
printf("[%f -> %d] ",2.0,isPowOf2(2.0)); // [2.000000 -> 1]
printf("[%f -> %d] ",4.0,isPowOf2(4.0)); // [4.000000 -> 0]
printf("[%f -> %d] ",0.25,isPowOf2(0.25)); // [0.250000 -> 0]
printf("[%f -> %d]\n ",11.0,isPowOf2(11.0)); // [11.000000 -> 0]
Could you please explain what's the problem? 您能解释什么问题吗?
The reason for failure is the wrong number of bits in the significand. 失败的原因是有效位数错误。
In the case of float
23 bits are stored of 24. 对于
float
将存储23位。
In the case of double
52 bits are stored of 53. 在
double
的情况下,存储了53个位。
Having corrected that, and added the LL
qualifier (as mentioned in comments) the offending line becomes 更正了这一点,并添加了
LL
限定符(如注释中所述),违规行变为
if((bitset.intRepresent & ((1LL << 52)-1)) != 0) {
and gives the same result as for float
. 并给出与
float
相同的结果。
Code is performing an invalid shift. 代码正在执行无效的移位。
1
is an int
. 1
是一个int
。 A long long
is needed. 需要
long long
。 @Robᵩ @罗ᵩ
union {
double floatRepresent;
long long intRepresent;
} bitset;
// if((bitset.intRepresent & ((1 << 53)-1)) != 0)
if((bitset.intRepresent & ((1LL << 53)-1)) != 0)
Code is using the wrong constant. 代码使用了错误的常量。 An IEEE 754 binary64
double
has a 52 bit encoded significand. IEEE 754 binary64
double
编码有效位数为52位。 @njuffa @njuffa
// if((bitset.intRepresent & ((1 << 53)-1)) != 0)
if((bitset.intRepresent & ((1LL << (53-1))-1)) != 0)
Code also does not properly work with +infinity. 代码也无法正确使用+ infinity。
// return power > 0 && power < 2047;
return power > 0 && power < 1023; // Candidate fix for infinity.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.