亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++中double浮點數(shù)精度丟失的深入分析

 更新時間:2021年01月05日 16:07:12   作者:adanus  
這篇文章主要給大家介紹了關(guān)于C++中double浮點數(shù)精度丟失的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

看了一篇關(guān)于C/C++浮點數(shù)的博文,在Win32下,把int, 指針地址,long等4字節(jié)整數(shù)賦給一個double后,再用該double數(shù)賦給原始類型的數(shù),得到的結(jié)果于最初的數(shù)值一致,即不存在任何精度丟失。例如下面的結(jié)果將總是true:

 long a=123456; //assign any long number here
 double db=a;
 long b=db;
 printf("%s\n",a==b?"true":"false");

但是對于long long或win64下的指針地址等8字節(jié)整數(shù)將存在精度丟失,于是對這方面做了一個簡單的測試:

#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(){
 
 unsigned long long maxULL=0xffffffffffffffff; //2^64-1=18446744073709551615,
             //max unsigned long long
 printf("%llu\n",maxULL);

 double d1=maxULL;        //20bit Significant,Precision Loss 
 printf("%f\n",d1);      

 maxULL=d1;
 printf("%llu\n",maxULL);
 
 showEncodeOfDouble((unsigned char*)&d1);

 system("pause");
 return 0;
}

輸出的結(jié)果如下(visual studio,win32):

18446744073709551615
18446744073709552000.000000
9223372036854775808
 43 f0 00 00 00 00 00 00

至此,有兩點疑問(暫時不理會代碼中showEncodeOfDouble的結(jié)果):

  1)為什么丟失精度后得到的double數(shù)是18446744073709552000.000000?
  2)為什么將double數(shù)重新轉(zhuǎn)化為unsigned long long后得到的數(shù)又和double不一致呢?

對于這兩個問題,需要對C++浮點數(shù)的規(guī)格有一定的了解。

1  IEEE浮點標(biāo)準(zhǔn)

C/C++采用的是IEEE浮點標(biāo)準(zhǔn),它以“二進(jìn)制的科學(xué)表示法”表示一個小數(shù):

其中M是一個整數(shù)部分僅有一位的二進(jìn)制小數(shù),例如1.011,表示十進(jìn)制下的1.375。E表示該小數(shù)以2為底時的階數(shù)?;谝陨系谋硎痉绞剑?shù)需要對三部分進(jìn)行編碼:表示符號的s,及階碼E、尾數(shù)碼M。C++中的double類型三種編碼所占的位數(shù)如圖所示。

53位尾數(shù)碼所能達(dá)到的精度為53二進(jìn)制位,約為16 個十進(jìn)制位( 53 log10(2) ≈ 15.955) [1],尾數(shù)碼的編碼中還有一個隱含的開頭整數(shù)位1(或0,當(dāng)11位階碼全0時)因此實際中可得15-17位十進(jìn)制的精度。當(dāng)有效位數(shù)最多15位的十進(jìn)制數(shù)轉(zhuǎn)換成double然后重新轉(zhuǎn)換為原來的十進(jìn)制類型時,數(shù)值保持一致;另一方面,將一個double數(shù)轉(zhuǎn)化為可以容納17位以上有效數(shù)字的十進(jìn)制數(shù)再重新轉(zhuǎn)化為double,結(jié)果數(shù)值也保持一致。

這就解釋了為什么4字節(jié)的整數(shù)轉(zhuǎn)化為double重新轉(zhuǎn)化能保持一致(2^32=4294967296僅10個有效位),而8字節(jié)的整數(shù)卻可能丟失精度(2^64-1=18446744073709551615共20個有效位)。但第一個問題中整數(shù)丟失精度后轉(zhuǎn)化成的double數(shù)值是怎么來的呢,這需要了解C++階碼和尾數(shù)對于double數(shù)值的意義。

2 階碼編碼和尾數(shù)編碼

在階碼編碼中,有一個常數(shù)偏置量Bias=1023,假設(shè)11位階碼所代表的無符號整數(shù)值為e,

1)若e不為0(11位全為1時用于表示特殊數(shù)字,此處不討論),則double數(shù)值為

2)若e=0,則小數(shù)值為

 

那么,可以看函數(shù)showEncodeOfDouble了,它的作用是將一個double數(shù)的編碼按字節(jié)打印出來(左邊是高字節(jié)),按其打印結(jié)果按照上面計算,可知double編碼值表示的數(shù)值是2^64,這是合理的,當(dāng)把精度較高的整數(shù)轉(zhuǎn)化為double時,C++采用向偶數(shù)舍入的方式得到最接近的值[2]。至于打印出的結(jié)果,屬于C++浮點數(shù)打印中的細(xì)節(jié)問題。

3 C++浮點數(shù)打印

許多C/C++的庫中在輸出double時,通常有意使得輸出結(jié)果簡短些(即使設(shè)置了足夠多的可見位數(shù)),以避免較大位數(shù)的輸出。直接使用C中的printf或cout打印double數(shù)時,打印顯示的結(jié)果也有可能是帶有精度丟失的結(jié)果,可使用16進(jìn)制的方式打印出更精確的double:

printf("%a\n",d1);

得到的輸出結(jié)果為:

0x1.000000p+64

至此問題1實際上只是C++中,將高精度整數(shù)轉(zhuǎn)double時的偶數(shù)舍入問題。

對于問題2,從float或double轉(zhuǎn)換成int,值將會被向零舍入.例如1.999將被轉(zhuǎn)換成1而-1.999將會被轉(zhuǎn)換成-1。進(jìn)一步來說,值有可能會溢出。C語言標(biāo)準(zhǔn)沒有對這種情況指出固定的結(jié)果,這種轉(zhuǎn)換行為是無定義的。

參考鏈接:

[1] http://en.wikipedia.org/wiki/Double-precision_floating-point_format#cite_note-whyieee-1

[2]深入理解計算機(jī)系統(tǒng),Randal E. Bryant, 機(jī)械工業(yè)出版社

[3]http://stackoverflow.com/questions/4738768/printing-double-without-losing-precision

到此這篇關(guān)于C++中double浮點數(shù)精度丟失的深入分析的文章就介紹到這了,更多相關(guān)C++ double浮點數(shù)精度丟失內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言自研定時器計劃任務(wù)語法詳解

    C語言自研定時器計劃任務(wù)語法詳解

    市面主流定時器計劃任務(wù)語法: cron ,但是使用起來非常難受,設(shè)計的比較非人性話語法,我想一般人都沒幾個記住的,所以本文將自研定時器計劃任務(wù)語法,需要的可以參考一下
    2022-09-09
  • C++函數(shù)對象詳解附帶實例

    C++函數(shù)對象詳解附帶實例

    這篇文章主要介紹了C++函數(shù)對象詳解附帶實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • C語言實現(xiàn)旅游景點咨詢系統(tǒng)

    C語言實現(xiàn)旅游景點咨詢系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)旅游景點咨詢系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C語言開發(fā)實現(xiàn)掃雷游戲

    C語言開發(fā)實現(xiàn)掃雷游戲

    這篇文章主要為大家詳細(xì)介紹了C語言開發(fā)實現(xiàn)掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • Qt音視頻功能實現(xiàn)方法詳解

    Qt音視頻功能實現(xiàn)方法詳解

    音視頻應(yīng)用往往需要大量的計算資源,尤其是在處理高分辨率、高碼率的音視頻數(shù)據(jù)時,這篇文章主要給大家介紹了關(guān)于Qt音視頻功能實現(xiàn)方法的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-09-09
  • Dev C++編譯時運行報錯source file not compile問題

    Dev C++編譯時運行報錯source file not compile問題

    這篇文章主要介紹了Dev C++編譯時運行報錯source file not compile問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • C++掃雷游戲的簡單制作

    C++掃雷游戲的簡單制作

    這篇文章主要為大家詳細(xì)介紹了C++掃雷游戲的簡單制作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • C++定義和初始化string對象實例詳解

    C++定義和初始化string對象實例詳解

    這篇文章主要為大家介紹了C++定義和初始化string對象實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • C++實現(xiàn)翻轉(zhuǎn)單詞順序

    C++實現(xiàn)翻轉(zhuǎn)單詞順序

    這篇文章給大家匯總介紹了C++實現(xiàn)翻轉(zhuǎn)單詞順序的三種方法,都非常的簡單,需要的朋友可以參考下
    2016-07-07
  • C++代碼實現(xiàn)掃雷游戲

    C++代碼實現(xiàn)掃雷游戲

    這篇文章主要為大家詳細(xì)介紹了C++代碼實現(xiàn)掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12

最新評論