咱們知道,任何數據在計算機內存中都是用‘0\1’來存儲的,浮點數亦是如此。所以十進制浮點數在存儲時一定會轉換爲二進制的浮點數。code
主要看看十進制轉二進制,整數部分和小數部分分開處理blog
整數部分:整數除以2,獲得一個商和餘數,獲得的商繼續除以2並獲得一個商和一個餘數,繼續除以2操做直至商爲0,上述操做獲得一系列餘數,從最後一個餘數開始直至第一個餘數,這一系列0\1即爲轉換後的二進制數。ip
小數部分:乘以2,而後取出整數部分,將剩下的小數部分繼續乘以2,而後再取整數部分,一直取到小數部分爲零爲止。若是永遠不爲零,則按要求保留足夠位數的小數,最後一位作0舍1入。將取出的整數順序排列。內存
從以上轉換過程能夠看出,並非任何一個十進制小數均可以用二進制精確表示出來。一個在0到1之間的小數P可用以下形式表示:get
從這個式子中咱們也可看出二進制表示出的小數是分段的,這也是爲何在Java中浮點數不少時候並非十分精確的表示十進制小數的根本緣由。io
float在Java中是4字節(32位),取值範圍大約-3.4E+38F~3.4E
+38F。二進制
爲何取值範圍是這個呢?float
二進制在內存中使用二進制的科學計數法來存儲,所以分爲階碼(即指數)和底數,因爲也有正負之分,因此還有一位符號位。im
最高位爲符號位,接着8位階碼,剩下23位爲底數。數據
值得注意的是,不管底數是什麼值,咱們均可以進行移位操做,使得底數=1.xxxxxx,這相似於十進制中的任意一個數轉換爲用科學計數法表示時進行的移位操做。因爲底數前的一個1是固定不變的,故將其省略(爲了表示更大的範圍)。也就是說實際上底數是24位。
底數能夠表示的最大值爲1.1111111111111111111111111(共24個1),轉換爲十進制的值約爲1.999999(接近於2)。
底數的最小值爲1.00000000000000(23個0),轉換爲十進制爲1。
故可知,底數取值在1~2之間。
階碼在這裏用移碼表示,採用偏移值爲127的移碼,爲何要這樣作?浮點數的階碼中,全0和全1被保留做特殊狀況,因此實際只有254個值可用。
階碼一定是有負值的,那麼如何最優雅地表示負值呢?爲了讓計算機很容易比較階碼大小(以此來比較浮點數的大小),同時人也能夠很輕鬆地辨別大小,由於移碼至關於實際值在數軸上平移了必定位數。
我以爲應該是爲了平衡精度與範圍,而且讓表示的範圍儘量大。
階碼用移碼錶示後,8位二進制從1~254以此表示爲-126~127。不只去除了全0和全1的狀況,還能讓人一眼看出兩個階碼的大小。
知道階碼和底數的範圍後,就能夠得出float的取值範圍:
轉化爲十進制爲
-3.4*10^38~-1.2*10^(-38)
與1.2*10^(-38)~3.4*10^38