Java比較兩個浮點數


浮點數的基本數據類型不能用==比較,包裝數據類型不能用 equals 比較

浮點數的表示

在計算機系統中,浮點數采用 符號+階碼+尾數 進行表示。在Java中,單精度浮點數float類型占32位,它的二進制表示方式為:

  • 符號位:1位,0表示正數; 1表示負數
  • 指數位:8位,用來表示指數(要加上偏移量)
  • 小數位:23位,用來表示小數

實際上計算機中的浮點數表示方法和科學技術法類似,小數的位數決定了浮點數的精度。當一個十進制的小數轉換成二進制時,很有可能無法使用這么多小數位表示它。因此使用浮點數的時候,實際存儲的尾數是被截取或者舍入之后的值。因此使用浮點數進行計算的時候就不得不考慮精度問題,即浮點數無法精確計算。

如何比較浮點數

1. 不能使用==

對於浮點數,我們無法使用==或者包裝類型的equals()來精確比較。例如:

// 對f1執行11次加0.1的操作
float f1 = 0.0f;
for (int i = 0; i < 11; i++) {
    f1 += 0.1f;
}
// f2是0.1*11的結果
float f2 = 0.1f * 11;
System.out.println(f1 == f2);   // 結果為false

執行上述代碼,會得到二者不相等,同時如果打印f1和f2,會得到如下結果:

f1 = 1.1000001
f2 = 1.1

可以看到,在浮點數的運算過程中,確實出現了精度問題。

2. 規定誤差范圍

盡管無法做到精確比較,但是我們可以確定一個誤差范圍,當小於這個誤差范圍的時候就認為這兩個浮點數相等。例如:

final float THRESHOLD = 0.000001;   // 設置最大誤差不超過0.000001
float f1 = 0.0f;
for (int i = 0; i < 11; i++) {
    f1 += 0.1f;
}

float f2 = 0.1f * 11;

if (Math.abs(f1 - f2) < THRESHOLD) {
    System.out.println("f1 equals f2");
}

3. 使用BigDecimal

BigDecimal是一個不可變的、能夠表示大的十進制整數的對象。注意使用BigDecimal時,要使用參數為String的構造方法,而不要使用參數為double的構造方法,防止產生精度丟失。使用BigDecimal進行運算,使用它的compareTo()方法比較即可。
示例:

private void compareByBigDecimal() {
    BigDecimal f1 = new BigDecimal("0.0");
    BigDecimal pointOne = new BigDecimal("0.1");
    for (int i = 0; i < 11; i++) {
        f1 = f1.add(pointOne);
    }

    BigDecimal f2 = new BigDecimal("0.1");
    BigDecimal eleven = new BigDecimal("11");
    f2 = f2.multiply(eleven);

    System.out.println("f1 = " + f1);
    System.out.println("f2 = " + f2);

    if (f1.compareTo(f2) == 0) {
        System.out.println("f1 and f2 are equal using BigDecimal");
    } else {
        System.out.println("f1 and f2 are not equal using BigDecimal");
    }
}

參考鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM