1. 程式人生 > >如何理解IEEE 754標準對Java中float值和double值的規定

如何理解IEEE 754標準對Java中float值和double值的規定

rac tro zh-cn 分享圖片 編號 如何 ins font 指數

在Java語言中,我們可以使用float和double這兩種基本數據類型來表示特定的數據。

這兩種數據類型,本質上是浮點數(floating-point number),浮點是一種對於實數的近似值數值表現法,由一個有效數字加上冪數來表示。

之所以使用浮點數,是因為計算機在使用二進制運算的過程中,無法將所有的十進制小數準確的換算為二進制,只能使用近似值來表示。

使用浮點數表示數值的方法很多,在Java中,和C語言一樣,float和double都采用了使用最為廣泛的IEEE 754標準。

IEEE 754標準的全稱為IEEE二進制浮點數算術標準(ANSI/IEEE Std 754-1985),其中ANSI是美國國家標準學會(American National Standards Institute)的縮寫,IEEE是電器電子工程師學會(Institute of Electrical and Electronics Engineers)的縮寫,754是該標準的編號,1985則是該標準發布的年份。

IEEE 754規定,一個二進制浮點數在存儲中由三部分組成:

技術分享圖片

其中第一部分為符號位(sign bit),第二部分為指數偏移值(exponent bias)用於存儲浮點數的指數部分,第三部分為分數(fraction)用於存儲浮點數的有效數的小數部分。

以一個具體的float值為例,Java中的float值采用的是IEEE754中的單精度標準,使用32個比特進行存儲。例如:

0100 0100 1010 0110 1001 1110 0000 0000

其中:

0100 0100 1010 0110 1001 1110 0111 0100

第一位的0為符號位,它表示這個數的正負值為正,相應的,若第一位為1則表示這是一個負數;

0100 0100 1010 0110 1001 1110 0000 0000

第2~9的8個比特存儲的是指數偏移值

,用於記錄該float值的指數部分,取值範圍為-126~+127再加上偏移值127(2的7次方減1),結果就是1~254(0和255留作特殊值)。在本例中,1000 1001在十進制中的值為137,但是137是進行偏移後的結果,減去偏移值127後,其實際代表的指數值就是10。

0100 0100 1010 0110 1001 1110 0000 0000

第10~32的23個比特存儲的是該float值的分數/小數部分。010 0110 1001 1110 0000 0000實際上表示的就是二進制的0.010 0110 1001 1110 0000 0000再加上1,也就是1.010 0110 1001 111。這實際上就是二進制的1010 0110 1001 111右移十四位的結果。1010 0110 1001 111在十進制中的值為21327,所以1.010 0110 1001 111也就等於21327*2^(-14)。

綜上,例子中的:

0100 0100 1010 0110 1001 1110 0000 0000

實際上也就等於:

+        21327*2^(-14)   *   2^10    =  1332.9375

第一位符號位表示 第10~32的分數位表示  第2~9的指數位表示

反之,例如我們想知道某個float a = 1000在內存中的形式,那麽則需要如下操作:

首先,1000是個整數,所以第一個比特位存儲的是0。

十進制的100在二進制中為11 1110 1000,這實際上就是1.111101左移9位的結果,
那麽實際上指數位存儲的結果就應該是9 + 127 = 136也就是1000 1000

分數位存儲的則是1.111101減去1的部分,補齊23位,也就是111 1010 0000 0000 0000 0000

綜上float a = 1000在內存中的存儲為:

0100 0100 0111 1010 0000 0000 0000 0000

另外,前面提到過的,指數偏移值為0或255的時候代表特殊值:

當指數值為0,即0000 0000時,若小數部分為0,則這個數為±0(正負由符號位決定);

當指數值為255,即1111 1111時,若小數部分為零,則這個數為±∞(正負由符號位決定);

當指數值為255,即1111 1111時,若小數部分非零,則這個數表示為不是一個數(Not a Number)。

以上就是float的部分,double同理,只不過double采用IEEE 754雙精度標準,使用64個比特存儲,其中2~12的11位為指數位,13~64的52位為小數位。

References:

IEEE 754 - wiki
https://zh.wikipedia.org/zh-cn/IEEE_754

浮點數 - wiki
https://zh.wikipedia.org/zh-cn/%E6%B5%AE%E7%82%B9%E6%95%B0

如何理解IEEE 754標準對Java中float值和double值的規定