簡體   English   中英

執行涉及非終止BigDecimals的算法

[英]Performing arithmetic involving non-terminating BigDecimals

當分割BigDecimal時,結果可能會是非終止的。 因此,您必須提供MathContext或RoundingMode / scale作為除法運算的一部分。 但是,根據算術中的運算順序,精度的損失可能會導致差異。

使用BigDecimals時,如何避免由於精度損失(如以下示例所示)引起的差異? 很想知道其他人如何處理此類問題。

例:

BigDecimal v1 = new BigDecimal("29.14");
BigDecimal v2 = new BigDecimal("12");
BigDecimal v3 = new BigDecimal("75");
System.out.println(v1.divide(v2, MathContext.DECIMAL64).multiply(v3).setScale(2, RoundingMode.HALF_UP));
// Prints: 182.12
System.out.println(v1.multiply(v3).divide(v2, MathContext.DECIMAL64).setScale(2, RoundingMode.HALF_UP));
// Prints: 182.13

在上面的示例中,根據操作順序,結果會更改。

在測試過程中運行此示例之前,我從未考慮過BigDecimal操作的順序是個問題。 現在,我面臨着這個難題:)

這是浮點算術的普遍問題,無論是二進制還是十進制:除法可能都不准確。 因此,當您必須進行乘法和除法運算時,如果先進行除法運算而結果是不准確的,那么在以后進行乘法運算時,就需要乘以第一個結果的誤差。

在您的示例中,准確的結果是182.125,該結果恰好在要舍入為182.13的邊界中。 當您首先進行除法時,29.14 / 12的確切結果是2.428333 ...

用DECIMAL64的16位數字四舍五入到2.428333333333333,再乘以75,得到182.12499999999997,將四舍五入到182.12。

那么可以在這里做什么:

  • 如果沒有溢出風險,請先進行乘法運算,然后除法。 例如對於a/b*c/d您應該計算(a*c)/(b*d)
  • 使用小數時,請嘗試添加一個精度數字。 在這里,您應該使用3個十進制數字的精度,因為初始數字由2個給定。 在兩種情況下,結果都是182.125

但是無論如何,一旦沒有確切的結果,就有可能會產生舍入誤差,這是浮點計算所固有的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM