Java中的小數是怎麼存儲的?

Java中的小數使用double和float表示,小數屬於浮點型(默認爲double)。

對於float型的值,則要在數字後加f或F,如12.3F,它在機器中佔32位,4個字節來存儲,表示精度較低。double是64位。

那麼一個小數在Java中是如何存儲的呢?

1.Java語言中,float類型數字在計算機中的存儲遵循IEEE-754格式標準:

(1)一個浮點數有3部分組成:符號位,指數部分e和底數部分m。

(2)浮點數需要用二進制來表示,所以底數m部分:使用二進制數來表示此浮點數的實際值。

(3)指數可正可負,所以,IEEE規定,此處算出的次方必須減去127纔是真正的指數。因此指數部分有偏移量(float爲127, double爲1023)所以,float類型的指數可從-126到128。

(4)float類型符號位佔1位,指數部分佔用8bit(1個字節)的二進制數,可表示數值範圍爲0-255,尾數佔23位(因爲規格化表示,小數點左邊的就是最高位一定爲1,最高位省去不存儲,在存儲中佔23bit,實際有24位精度)

(5)double類型符號位佔1位,指數部分佔11位,尾數佔52位(因爲規格化表示,小數點左邊一定爲1,所以實際有53位精度)

根據上面的描述。浮點數科學計數法的個數如下:

SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM

S表示浮點數正負;E表示指數加上127後的值後得二進制數據;M表示底數。

下面舉兩個例子看下小數在Java中的存儲過程。

(1)17.625在內存中的存儲爲:

<1>首先要把17.625換算成二進制:10001.101

整數部分換算成二進制:整數遞歸的除以2,直到商爲0,餘數反轉。(即:模2取餘法)

17 / 2 = 8 --- 1

8 / 2 = 4 --- 0

4 / 2 = 2 --- 0

2 / 2 = 1 --- 0

1 / 2 = 0 --- 1

小數部分:乘以2,直到乘位爲0,進位順序取。(即:乘2取整法)

按如下算法進行: 

1)首先給小數部分乘2,得到的數,如果小數點前爲1;則計1,爲0,則計0。 

2)再對剩下的小數部分乘2,再計出1或0。 

3)重複以上步驟,直至達到需要的精度。

0.625 x 2 = 1.3   --- 計爲1

0.3 x 2 = 0.6       --- 計爲0

0.6 x 2 = 1.2       --- 計爲1

0.2 x 2 = 0.4       --- 計爲0

 ......(算到需要的精度爲止) 

再例如:

0.5 x 2 = 1.0     --- 計爲1

0 x 2 = 0    --- 結束

所以:0.5(D) = 0.1(B)

      十進制      二進制

<2>得到17.625的二進制,再將10001.101右移,直到小數點前只剩1位:

1.0001101 * 2^4,右移了四位,這個時候,二進制的底數和指數就出來了。

底數:因爲小數點前必爲1,所以IEEE規定只記錄小數點後的就好。所以,此處的底數爲:0001101,

指數:實際爲4,必須加上127(轉出的時候,減去127),所以爲131。也就是10000011,

符號部分是正數,所以是0。

綜上所述,17.625在內存中的存儲格式是:0(符號位)1000001 1(指數)0001101 00000000 00000000(底數) 

(2)再看一個例子float 0.6

<1>把十進制轉2進制

0.6的二進制表示(乘2取整,順序表示):.1001 1001 1001 1001 1001 1001 1001 ... 無限循環下去。

<2>計算尾數部分

把.1001 1001 1001 1001 1001 1001 1001 ...規格化表示(小數點移到第一個非0書右邊)就是:

1.001 1001 1001 1001 1001 1001 1001 ...,右移了1位。

由於規格化表示的數小數點左邊一定爲1,把這個1捨棄,並保留float尾數能表示的23位,最終尾數部分是:

001 1001 1001 1001 1001 1001

<3>計算指數部分: 由於計算尾數時右移了1位,相當於乘以2的負1次,所以指數爲-1,加上float偏移量127,最後指數爲126, 二進制表示爲 0111 1110

<4>符號部分: 0.6爲正數,符號位爲0

最終0.6在計算機中的表示就是:

符號位    指數              尾數

   0    0111 1110  001 1001 1001 1001 1001 1001

(3)現在再從這個2進制來計算10進制數:(尾數*2的指數 )

符號位0--> 爲正

指數 0111 1110:爲126, 減去偏移量127,結果爲-1.

尾數 001 1001 1001 1001 1001 1001: 規格化的時候小數點左邊去掉了一個1,現在加上:

1.001 1001 1001 1001 1001 1001,轉爲10進制就是:

1*2^0 + 1*2^-3 + 1*2^-4 + .....= 1.19999992847442626953125

1.19999992847442626953125 * (2^-1) = 0.599999964237213134765625

所以最終結果是一個無限接近於0.6而不能精確表示0.6。在計算機中浮點數就是表示的近似值。

參考:(1)https://www.cnblogs.com/chenmingjun/p/8415464.html

           (2)https://bbs.csdn.net/wap/topics/360184754

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章