Java中的小數使用double和float表示,小數屬於浮點型(默認爲double)。算法
對於float型的值,則要在數字後加f或F,如12.3F,它在機器中佔32位,4個字節來存儲,表示精度較低。double是64位。遞歸
那麼一個小數在Java中是如何存儲的呢?內存
1.Java語言中,float類型數字在計算機中的存儲遵循IEEE-754格式標準:it
(1)一個浮點數有3部分組成:符號位,指數部分e和底數部分m。循環
(2)浮點數須要用二進制來表示,因此底數m部分:使用二進制數來表示此浮點數的實際值。二進制
(3)指數可正可負,因此,IEEE規定,此處算出的次方必須減去127纔是真正的指數。所以指數部分有偏移量(float爲127, double爲1023)因此,float類型的指數可從-126到128。float
(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。在計算機中浮點數就是表示的近似值。