都知道十進制整數轉換二進制( / 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));