float為什麼比int表示的範圍廣? 什麼是單精度和雙精度? float表示小數的時候為什麼會有精度丟失? 帶著這幾個問題,我們來探究下java中float類型在電腦的表示形式。 java中int占用4個位元組,float也是占用4個位元組,但是為什麼float表示的範圍要比int大呢,因為兩者在計 ...
float為什麼比int表示的範圍廣?
什麼是單精度和雙精度?
float表示小數的時候為什麼會有精度丟失?
帶著這幾個問題,我們來探究下java中float類型在電腦的表示形式。
java中int占用4個位元組,float也是占用4個位元組,但是為什麼float表示的範圍要比int大呢,因為兩者在電腦內中表示的方式不一樣,int是4個位元組32位,每一位都是二進位小數表示,最高位0代表是正數,最高位為1代表是負數,所以int的範圍是-2^31~2^31-1;
float也是4個位元組,遵循IEEE-754格式標準,在電腦中表示有三個部分組成:符號s底數m和指數e。
符號s:最高位,0為正數;1為負數,占用一位;
指數e:是該浮點數的指數,二進位表示,最高位為指數符號為1表示大於1,0表示小於1,其實他是用的偏移量表示的,偏移大小為127,沒有用補碼表示,占用一個位元組8位;
底數m:是該浮點數的實際值,二進位形式表示,m的範圍是【1,2】或者【0,1】占用23位。
所以float在電腦的表示如下麵所示:
SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
我們先說下10進位和二進位的快速轉換方法。
10進位整數2進位轉換是除2求商和餘數,比如十進位17的二進位計算為:
17 /2=16餘1
16 /2= 8 餘0
8 /2= 4 餘0
4 /2= 2 餘0
2 /2= 1 餘0
1 /2= 0 餘1
一直計算到商為0為止,17的二進位表示就是:10001
10進位小數2進位表示是乘2求積,比如0.16的二進位計算為:
0.16*2=0.32取0
0.32*2=0.64取0
0.64*2=1.28取1
0.28*2=0.56取0
0.56*2=1.12取1
0.12*2=0.24取0
。。。
所以0.16的二進位表示就是001010..... 一直迴圈下去,所以除非小數最後為5才能*2取整,否則都會無線迴圈下去,這就是為什麼浮點小數精度丟失的問題。
下麵我們距離來說明10進位浮點數在電腦的表示, 拿17.16來說:
1.首先為正數,s為0
2.二進位為10001.0010100011110101....小數點左移4位為1.00010010100011110101...
3.指數位為4+127=10000011,所以指數位位10000011
4.由於預設最左邊為1,所以底數為00010010100011110101...
5.最後17.16的二進位表示就是:01000001100010010100011110101......總共32位,後面的捨棄
再拿0.16舉例:
1.首先為整數,s為0
2.二進位為0.0010100011110101......小數點右移4位為1.0100011110101
3.指數位為4+127=10000011,然後取反為01111100,所以指數位位01111100
4.底數位0100011110101...
5.最後0.16的二進位表示就是:0011111000100011110101...
float的(正數)範圍:
最小值:Float.MIN_VALUE=1.4E-45 (2的-149次方:指數位127+底數22)
最大值:Float.MAX_VALUE=3.4028235E38 (2的128次方-1)
float是單精度浮點數,4個位元組;double是雙精度浮點數,8個位元組,e占11位,m占52位。
註意事項:
1.價格在資料庫中保存建議是無符號整形,避免在java轉換成浮點數時出現精度丟失的問題;
2.如果需要用浮點型數據進行運算,建議使用BigDecimal,但是BigDecimal的構造函數一定要使用字元串的,否則一樣會出現精度丟失的問題:BigDecimal(“123f”)而不是BigDecimal(123f)。
3.Float.MIN_VALUE是:1.4E-45,不是一個負數,double也是的。但是整型的MIN_VALUE都是負數
4.float的m只有23位,2^23=8388608,總共有7位10進位數字,由於最左邊的1省略了,所以表示的有效數字最高精確度位7~8位,包括整數部分,8位後的數字肯定不是準確的