我找到了检查浮点数是否为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]
正如您在评论中看到的那样,它没有任何问题。但是,当我尝试将此程序转换为双数字版本时,它会产生错误的结果:
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]
你能解释一下这是什么问题吗?
答案 0 :(得分:2)
失败的原因是有效数字中的位数错误。
在float
的情况下,存储了24位。
在double
的情况下,52位存储为53。
更正了这一点,并添加了LL
限定符(如评论中所述)违规行变为
if((bitset.intRepresent & ((1LL << 52)-1)) != 0) {
并给出与float
相同的结果。
答案 1 :(得分:1)
代码执行无效转移。 1
是int
。需要long long
。 @Robᵩ
union {
double floatRepresent;
long long intRepresent;
} bitset;
// if((bitset.intRepresent & ((1 << 53)-1)) != 0)
if((bitset.intRepresent & ((1LL << 53)-1)) != 0)
代码使用了错误的常量。 IEEE 754 binary64 double
具有52位编码的有效数字。 @njuffa
// if((bitset.intRepresent & ((1 << 53)-1)) != 0)
if((bitset.intRepresent & ((1LL << (53-1))-1)) != 0)
代码也无法正常使用+无穷大。
// return power > 0 && power < 2047;
return power > 0 && power < 1023; // Candidate fix for infinity.