Java中的舍入誤差


編寫程式碼時,我們都會犯各種錯誤,這些錯誤會導致溢位錯誤和語法錯誤等問題。舍入誤差是一種常見的錯誤,可能會導致給定數學問題的錯誤解決方案。通常,這種錯誤發生在我們使用浮點數時。

在本文中,我們將探討此問題的原因,並嘗試找到解決此類錯誤的方法。

舍入誤差

浮點型別

它們也稱為實數,在計算需要分數值時使用。它表示帶有小數點的數字。例如,要表示1/5的結果,即0.2,正弦和餘弦的結果也需要小數點。

在Java中,有兩種型別的浮點數:

  • float − 它可以儲存最大32位的單精度值。我們使用‘float’關鍵字宣告它。

  • double − 其大小比float大,可以儲存最大64位的雙精度值。它使用‘double’關鍵字宣告。

讓我們討論一個可能遇到舍入誤差的例子,然後我們將瞭解原因,並提供適當處理它的解決方案。

示例1

public class Main{
   public static void main(String[] args) {
      double data1 = 0.30;
      double data2 = 0.20 + 0.10;
      System.out.println("Value after addition: " + data2);
      System.out.println(data1 == data2);
      double data3 = 0.50;
      double data4 = 0.10 + 0.10 + 0.10 + 0.10 + 0.10;
      System.out.println("Value after addition: " + data4);
      System.out.println(data3 == data4);
   }
} 

輸出

Value after addition: 0.30000000000000004
false
Value after addition: 0.5
true

在上面的程式碼中,我們進行第一次加法運算時‘data2’的預期值是0.30,但在輸出中我們得到了錯誤的結果。但是,當我們進行另一次類似的加法運算時,我們得到了準確的結果。

讓我們來看另一個顯示錯誤的例子。

示例2

public class Main {
   public static void main(String[] args) {
      double data1 = 4.30452;
      double data2 = 0.503542;
      double res = data1 + data2;
      System.out.println("Value after addition: " + res);
   }
}

輸出

Value after addition: 4.8080620000000005

預期輸出是4.808062,但在這裡我們得到了錯誤的輸出。

錯誤原因

“IEEE 754”是Java在實現浮點數時遵循的標準。根據其“舍入”規則,當尾數的值大於23位時,它會將1加到第23位以舍入值。這裡,尾數是分數數字的二進位制表示。

這就是我們得到不同值的原因。

錯誤解決方案

為了避免這種舍入誤差,我們有以下幾種方法:

  • BigDecimal − 它是一個類,可以用作浮點數(如float和double)的替代。我們可以執行float和double資料型別提供的所有常規運算。例如,算術運算、比較和舍入。它可以以精確的精度處理這些運算。

以下示例演示瞭如何使用它來產生準確的結果。

示例3

import java.math.*;
public class Main{
   public static void main(String[] args) {
      BigDecimal data1 = new BigDecimal("0.20");
      BigDecimal data2 = new BigDecimal("0.10");
      BigDecimal res = data1.add(data2); // performing addition
      System.out.println("Value after addition: " + res);
   }
}

輸出

Value after addition: 0.30

在示例1中,我們在新增兩個值時出錯。在上面的示例中,我們使用了相同的值,但這次我們得到了正確的結果。

  • Math.round() − 它是‘Math’類的靜態方法。它接受一個浮點值作為引數,並返回最接近的整數值。我們使用其類名呼叫它。

下面的示例說明了它在程式中的用法。

示例4

public class Main {
   public static void main(String[] args) {
      double data1 = 4.30452;
      double data2 = 0.503542;
      double res = data1 + data2;
      System.out.println("Value after addition: " + res);
      System.out.println("Value after rounding off the addition: " + Math.round(res));
   }
}

輸出

Value after addition: 4.8080620000000005
Value after rounding off the addition: 5

結論

舍入誤差不是編譯時或執行時錯誤,Java編譯器無法檢測到它。這就是為什麼程式設計師需要格外注意這些錯誤,否則我們將得到錯誤的結果。在本文中,我們討論了原因,並提出了一些克服這種舍入誤差的方法。

更新於:2023年5月15日

790 次瀏覽

啟動您的職業生涯

完成課程獲得認證

開始學習
廣告
© . All rights reserved.