float double精度丟失

2021-07-22 18:01:40 字數 1721 閱讀 8563

本文參考略加補充。

都知道十進位制整數轉換二進位制( / 2),十進位制小數轉換二進位制( * 2 取 整),但小數有時乘不盡。

結論:

(1)整數永遠可以用二進位制精確表示

(2)小數的二進位制表示有時是不可能精確的

正如十進位制不法表示1/3, 二進位制也無法表示1/10;這也就解釋了為什麼浮點型減法出現了」減不盡」的精度丟失問題

而有時浮點數加減時小數點最後幾位出現了意外數字,傳送門:

這是因為浮點數所在記憶體的表示形式,符合ieee754標準。詳情 — 傳送門:

float記憶體儲存結構

float記憶體儲存結構

4bytes      31           30           29----23       22----0         

表示 實數符號位 指數符號位 指數字 有效數字

其中符號位1表示正,0表示負。有效位數字24位,其中一位是實數符號位。

將乙個float型轉化為記憶體儲存格式的步驟為:

(1)先將這個實數的絕對值化為二進位制格式,注意實數的整數部分和小數部分的二進位制方法在上面已經**過了。

(2)將這個二進位制格式實數的小數點左移或右移n位,直到小數點移動到第乙個有效數字的右邊。

(3)從小數點右邊第一位開始數出二十三位數字放入第22到第0位。

(4)如果實數是正的,則在第31位放入「0」,否則放入「1」。

(5)如果n 是左移得到的,說明指數是正的,第30位放入「1」。如果n是右移得到的或n=0,則第30位放入「0」。

(6)如果n是左移得到的,則將n減去1後化為二進位制,並在左邊加「0」補足七位,放入第29到第23位。如果n是右移得到的或n=0,則將n化為二進位制後在左邊加「0」補足七位,再各位求反,再放入第29到第23位。

舉例說明: 11.9的記憶體儲存格式

(1) 將11.9化為二進位制後大約是" 1011. 1110011001100110011001100..."。

(2) 將小數點左移三位到第乙個有效位右側: "1. 011 11100110011001100110 "。 保證有效位數24位,右側多餘的擷取(誤差在這裡產生了 )。

(3) 這已經有了二十四位有效數字,將最左邊一位「1」去掉,得到「 011 11100110011001100110 」共23bit。將它放入float儲存結構的第22到第0位。

(4) 因為11.9是正數,因此在第31位實數符號位放入「0」。

(5) 由於我們把小數點左移,因此在第30位指數符號位放入「1」。

(6) 因為我們是把小數點左移3位,因此將3減去1得2,化為二進位制,並補足7位得到0000010,放入第29到第23位。

最後表示11.9為: 0 1 0000010 011 11100110011001100110

可檢驗:
float f = 11.9f;

int i = float.floattointbits(f);

system.out

.println(integer.tobinarystring(i));

手動練習乙個。

float double 精度問題

延伸一下 float和double的範圍和精度。1.範圍 float和double的範圍是由指數的位數來決定的。float的指數字有8位,而double的指數字有11位,分布如下 float 1bit 符號位 8bits 指數字 23bits 尾數字 double 1bit 符號位 11bits 指...

float double精度和範圍

1.範圍 float和double的範圍是由指數的位數來決定的。float的指數字有8位,而double的指數字有11位,分布如下 float 1bit 符號位 8bits 指數字 23bits 尾數字 double 1bit 符號位 11bits 指數字 52bits 尾數字 於是,float的指...

float,double範圍和精度

今天遇到一題zoj 1128,資料範圍是 0 x1下面引用 1.範圍 float和double的範圍是由指數的位數來決定的。float的指數字有8位,而double的指數字有11位,分布如下 float 1bit 符號位 8bits 指數字 23bits 尾數字 double 1bit 符號位 11...