本文參考略加補充。
都知道十進位制整數轉換二進位制( / 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...