一个令人困惑的C++双数二进制编码结果

A Confusing Binary Encoding Result of C++ Double Number

本文关键字:C++ 二进制 结果 编码 一个      更新时间:2023-10-16

我知道IEEE双格式提供15–17个有效十进制数字的精度。将超过17个有效数字的十进制数转换为双精度类型将导致精度损失。例如:

#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("%fn",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? 

我参考了双类型的编码标准,发现它代表(-1)^0*2^64*1=2^64,我想知道为什么这样的编码被打印为18446744073709552000.000000。

43 f0 00 00 00 00 00 00对应的确切值为18446744073709551616。我不知道printf的具体规则,但许多库默认情况下会缩短输出,以避免打印大量任意数字。

例如,最接近1e100的双精度具有精确值10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104。这通常不是人们希望在打印1e100时看到的。大多数数字更多地与浮点表示的细节有关,而不是与它的实际使用有关。

您得到的值18446744073709552000.000000是所有转换回双精度的数字中有效位数最少的十进制数字,在小数点后显示6位数字,这是printf %f的默认值,因此它是格式化它的一个非常合理的选择。