浮點數計算中的精度丟失

2021-10-07 08:43:58 字數 2382 閱讀 8425

在記憶體中儲存的浮點數方法格式分別是

float      符號位(1bit)   指數(8 bit)     尾數(23 bit)

double   符號位(1bit)  指數(11 bit)   尾數(52 bit)

其中指數也有正負之分,有乙個bit位是符號位。

於是,float的指數範圍為-128   +127(     -2^7= -128   ——  2^7 -1=127) ;

而double的指數範圍為-1024  +1023(     -2^10= -1024  ——  2^10 -1=1023)

其中負指數決定了浮點數所能表達的絕對值最小的數;而正指數決定了浮點數所能表達的絕對值最大的數,也即決定了浮點數的取值範圍。

float的範圍為-2^128 ~ +2^127,也即-3.40e+38 ~ +3.40e+38;

double的範圍為-2^1024 ~ +2^1023,也即-1.79e+308 ~ +1.79e+308

2的0——10次方對應的十進位制數分別是

1     2      4      8      16     32    64(2^6)  128    256      512     1024(2^10)

浮點數實際就是用科學計數法記錄資料的。

科學計數法是一種簡化計數的方法,用來近似表示乙個極大或極小且位數較多的數,對於位數較小的數值,科學計數法沒有什麼優勢,但對於位數較多的數值其計數方法的優勢就非常明顯了。例如:光的速速是300000000公尺/秒,全世界人口數大約是6100000000。類似光的速度和世界人口數這樣大數值的數,讀、寫都很不方便,所以光的速度可以寫成3*10^8,全世界人口數可以寫成6.1*10^9。所以計算器用科學計數法表示光速是3e8,世界人口數大約是6.1e9。

十進位制的0.3  在二進位制裡是乙個無限迴圈小數0.01001100110011....  

十進位制的11.9化為二進位制後大約是   1011. 1110011001100110011001100…  

問題提出:12.0f-11.9f=0.10000038,」減不盡」為什麼?

計算12.0f-11.9f

12.0f 的記憶體儲存格式為: 0 1 0000010 100 0000000000 0000000000

11.9f 的記憶體儲存格式為: 0 1 0000010 011 1110011001 1001100110

可見兩數的指數字完全相同,只要對有效數字進行減法即可。

12.0f-11.9f 結果: 0 1 0000010 00000011001100110011010 

將結果還原為十進位制為: 0.000 11001100110011010= 0.10000038

把乙個無限迴圈的二進位制數放入不管是32還是64位的系統中都只能取其中的一部分儲存,被擷取的部分就是浮點數丟失精度的原因。

道理很簡單,十進位制不能準確表示出1/3。同樣的道理二進位制卻是無法準確表示1/10。

我們來看十進位制和二進位制計數的本質:

十進位制: 11.11= 1*10^1 + 1*10^0 + 1*10^-1 + 1*10^-2

二進位制: 11.11= 1*2^1 + 1*2^0 + 1*2^-1 + 1*2^-2

十進位制轉換成二進位制的過程:

十進位制1.6要轉化成二進位制需要分成兩部分整數部分和小數部分 。 整數部分要做的是: 除2取餘  1%2 = 1 ,這裡得到1  。

小數部分要做的是:乘2取整

0.6*2 = 1 + 0.2

0.2*2 = 0 + 0.4

0.4*2 = 0 + 0.8

0.8*2 = 1 + 0.6

0.6*2 = 1 + 0.2

...這裡你會發現得到的二進位制數值1.10011.... 是乙個無限迴圈的 二進位制小數。

為什麼會這樣? 其實十進位制中的0.5相當於一的一半,類似的二進位制中的0.1相當於一的一半。

那十進位制0.6代表著二進位制中0.1的1/6。

所以在十進位制的0.0到0.9中,只有0和0.5兩個十進位制數值有對應具體的二進位制數值表示。

所以答案就是,如果你把乙個無限迴圈的二進位制數放入不管是32還是64位的系統中肯定是只能取其中的一部分儲存,那被擷取的部分就是浮點數丟失精度的原因。

這也就解釋了為什麼浮點型減法出現了"減不盡"的精度丟失問題。

float和double型別是為了科學計算和工程計算而設計,它們在**裡呈現的是十進位制數字,在計算機儲存和運算時執行的是二進位制浮點運算, 它們是在廣泛的數值範圍上提供較為精確的快速近似計算而精心設計的。然而,float和double它們並沒有提供精確的結果,所以不應該被用於精確的結果的場合。浮點數使用科學計數法。十進位制小數轉換二進位制的時候會出現無限迴圈小數,而計算機儲存有限,因此被捨去的部分就是丟失的精度。

浮點數精度丟失問題

c 中的浮點數,分單精度 float 和雙精度 double float 是 system.single 的別名,介於 3.402823e38 和 3.402823e38 之間的32位數字,符合二進位制浮點演算法的 iec 60559 1989 ieee 754 標準 double 是 system...

浮點數的運算精度丟失

開啟python編譯器,輸入0.1 0.2,期待的結果是0.3,但是輸出為 0.30000000000000004 有點小尷尬,這是為什麼呢?其實這設計到了計算機的浮點數儲存是以二進位制進行儲存的。說二進位制不太形象,換成我們最長使用的十進位制和分數 1 5,使用小數表示為0.2,但是1 3,使用小...

浮點數的運算精度丟失

開啟python編譯器,輸入0.1 0.2,期待的結果是0.3,但是輸出為 0.30000000000000004 有點小尷尬,這是為什麼呢?其實這設計到了計算機的浮點數儲存是以二進位制進行儲存的。說二進位制不太形象,換成我們最長使用的十進位制和分數 1 5,使用小數表示為0.2,但是1 3,使用小...