[英]Why does the function work with float properly but doesn't work with double?
我找到了檢查浮點數是否為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]
您能解釋什么問題嗎?
失敗的原因是有效位數錯誤。
對於float
將存儲23位。
在double
的情況下,存儲了53個位。
更正了這一點,並添加了LL
限定符(如注釋中所述),違規行變為
if((bitset.intRepresent & ((1LL << 52)-1)) != 0) {
並給出與float
相同的結果。
代碼正在執行無效的移位。 1
是一個int
。 需要long long
。 @羅ᵩ
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)
代碼也無法正確使用+ infinity。
// return power > 0 && power < 2047;
return power > 0 && power < 1023; // Candidate fix for infinity.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.