我知道IEEE双格式给出15-17个有效十进制数字精度。将超过17位有效数字的十进制数转换为double类型将遇到精度损失。例如:
#include<iostream>
#include<stdlib.h>
void showEncodeOfDouble(unsigned char* db){
const int ByteLength=8;
for(int i=ByteLength-1;i>=0;i--)
printf(" %.2x",db[i]);
printf("\n");
}
int main(){
//2^64=18446744073709551616
double d1=18446744073709551616.0; //20bit Significant,Precision Loss
printf("%f\n",d1);
showEncodeOfDouble((unsigned char*)&d1);
return 0;
}
输出:
18446744073709552000.000000
43 f0 00 00 00 00 00 00
转换后,原来的20个有效小数位被切成只有17.我的问题是:
Why the encoding result is 43 f0 00 00 00 00 00 00?
我提到了double类型的编码标准符,发现这代表(-1)^ 0 * 2 ^ 64 * 1 = 2 ^ 64,我想知道为什么这样的编码被打印为18446744073709552000.000000。
答案 0 :(得分:0)
与43 f0 00 00 00 00 00 00
对应的确切值为18446744073709551616
。我不知道你的printf
的具体规则,但是许多库默认会缩短它们的输出,以避免打印大量的任意数字。
例如,与1e100
最接近的两倍具有精确值10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104
。这通常不是人们在打印1e100时想要看到的。大多数数字与浮点表示的细节有关,而不是与实际使用有关。
您获得的值18446744073709552000.000000
是十进制数字,其中有效数字的最小数字将转换回您的双精度数字,小数点后面的6位数字显示,这是{{1 }} printf
所以格式化它是一个非常合理的选择。