天天看點

Java之浮點數運算

  浮點數運算和整數運算相比,隻能進行加減乘除這些數值運算,不能做位運算和移位運算。

  在計算機中,浮點數雖然表示的範圍很大,但是浮點數有個非常重要的特點,就是浮點數常常無法精确表示

  舉例

  浮點數

0.1

在計算機中就無法精确表示,因為十進制的

0.1

換算成二進制是一個無限循環小數,很顯然,無論使用

float

還是

double

,都隻能存儲一個

0.1

的近似值。但是,

0.5

這個浮點數又可以精确地表示。因為浮點數常常無法精确表示,是以,浮點數運算會産生誤差:

public class Main {
    public static void main(String[] args) {
     double x=1.0 / 10;
     double y=1-9.0 / 10;
     System.out.println(x);
     System.out.println(y);
    }
}
      

   運作結果

0.1
0.09999999999999998
      

   由于浮點數存在運算誤差,是以比較兩個浮點數是否相等常常會出現錯誤的結果。正确的比較方法是判斷兩個浮點數之差的絕對值是否小于一個很小的數:

public class Main {
    public static void main(String[] args) {
     double x=1.0 / 10;
     double y=1-9.0 / 10;
     System.out.println(x);
     System.out.println(y);
     double r=Math.abs(x-y);
     if(r<0.00001) {
    	 System.out.println("true");
     }
     else {
    	 System.out.println("false");
     }
    }
}
      

   浮點數在記憶體的表示方法和整數比更加複雜。Java的浮點數完全遵循IEEE-754标準,這也是絕大多數計算機平台都支援的浮點數标準表示方法。

  類型提升

  如果參與計算的兩個數其中一個是整型,那麼整型可以自動提升到浮點型

public class Main {
    public static void main(String[] args) {
     int n=5;
     double d=1.2+24.0/n;
     System.out.println(d); //6.0
    }
}
      

   需要特别注意,在一個複雜的四則運算中,兩個整數的運算不會出現自動提升的情況。例如:

double d = 1.2 + 24 / 5; // 5.2
      

   計算結果為4.2,原因是編譯器計算24/5這個子表達式時,按兩個整數進行運算,結果為4,而不是按浮點運算4.8

  溢出

  整數運算在除數為

時會報錯,而浮點數運算在除數為

時,不會報錯,但會傳回幾個特殊值:

  • NaN

    表示Not a Number
  • Infinity

    表示無窮大
  • -Infinity

    表示負無窮大

  例如

double d1 = 0.0 / 0; // NaN
double d2 = 1.0 / 0; // Infinity
double d3 = -1.0 / 0; // -Infinity
      

   這三種特殊值使用較少

  強制轉型

  可以将浮點數強制轉型為整數,在轉型時,浮點數的小數部分會被丢棄。如果轉型後超過了整型能表示的最大範圍,将傳回整型最大值

public class Main {
    public static void main(String[] args) {
     int n1=(int) 12.3; //12
     System.out.println(n1); 
     int n2=(int) 12.7; //12
     System.out.println(n2); 
     int n3=(int) -12.7; //-12
     System.out.println(n3); 
     int n4=(int) 9999999991.11; //2147483647
     System.out.println(n4); 
    }
}
      

   小結

  浮點數無法精确表示,并且浮點數的運算結果可能有誤差。