1. 程式人生 > >Java中 float、double使用注意問題

Java中 float、double使用注意問題

在java中執行一下程式碼

System.out.println(2.00-1.10); 輸出的結果是:0.8999999999999999 很奇怪,並不是我們想要的值0.9

再執行如下程式碼: System.out.println(2.00f-1.10f); 輸出結果:0.9

又正確了,為什麼會導致這種問題?程式中為什麼要儘量避免浮點數比較?

在java中浮點型預設是double的,及2.00和1.10都要在計算機裡轉換進行二進位制儲存,這就涉及到資料精度,出現這個現象的原因正是浮點型資料的精度問題。先了解下float、double的基本知識:

  1. float和double是java的基本型別,用於浮點數表示,在java中float佔4個位元組32位,double佔8個位元組64位,一般比較適合用於工程測量計算中,其在記憶體裡的儲存結構如下:

float:

符號位(1 bit) 指數(8 bit) 尾數(23 bit)

double:

符號位(1 bit) 指數(11 bit) 尾數(52 bit)

注意:從左到右是從低位到高位,而在計算機內部是採用逆序儲存的。

  1. System.out.println(2.00-1.10);中的1.10不能被計算機精確儲存,以double型別資料1.10舉例計算機如何將浮點型資料轉換成二進位制儲存, 這裡重點講小數部分轉換成二進位制: 1.10整數部分就是1,轉換成二進位制1(這裡整數轉二進位制不再贅述) 小數部分:0.1 0.12=0.2取整數部分0,基數=0.2 0.22=0.4取整數部分0,基數=0.4 0.42=0.8取整數部分0,基數=0.8 0.8
    2=1.6取整數部分1,基數=1.6-1=0.6 0.62=1.2取整數部分1,基數=1.2-1=0.2 0.22=0.4取整數部分0,基數=0.4 . . . . 直至基數為0。1.1用二進位制表示為:1.000110…xxxx…(後面表示省略) 0.1 = 02(-1)+0*2(-2)+02(-3)+1*2(-4)+…而double型別表示小數部分只有52位,當向後計算 52位後基數還不為0,那後面的部分只能捨棄,從這裡可以看出float、double並不能準確表示每一位小數,對於有的小數只能無限趨向它。在計算機 中加減成除運算實際上最後都要在計算機中轉換成二進位制的加運算,由此,當計算機執行System.out.println(2.00-1.10); 時會拿他們在計算機記憶體中的二進位制表示計算,而1.10的二進位制表示本身就不準確,所以會出現0.8999999999999999的結果。

但為什麼System.out.println(2.00f-1.10f);得出的結果是0.9呢。因為float精度沒有double精度那麼大,小數部分0.1二進位制表示被捨去的比較多。

注意:

程式中應儘量避免浮點數的比較 float、double型別的運算往往都不準確