2012-08-29 70 views
6

可能重複:
ArithmeticException thrown during BigDecimal.divide劃分BigDecimals的結果ArithmeticException

這導致ArithmeticException:http://ideone.com/RXeZw

提供一個規模和舍入模式會給我錯誤的結果。這個例子應該輸出50.03%。如何正確舍入?

爲了便於參考,這是代碼:

BigDecimal priceDiff = BigDecimal.ONE 
    .subtract(new BigDecimal(9.99) 
    .divide(new BigDecimal(19.99))) 
    .multiply(new BigDecimal(100)); 
System.out.println(priceDiff.toPlainString()); 

回答

9

BigDecimal.divide(BigDecimal divisor)拋出ArithmeticException如果結果不能精確表示。
您將不得不使用提供MathContext或RoundingMode來告訴您如何處理此問題。例如:

public class Test { 
    public static void main(String[] args) throws java.lang.Exception { 
     BigDecimal priceDiff = BigDecimal.ONE.subtract(new BigDecimal("9.99").divide(new BigDecimal("19.99"), MathContext.DECIMAL128)) 
              .multiply(new BigDecimal(100)); 
     System.out.println(priceDiff.toPlainString()); 
    } 
} 

作品和版畫

50.0250125062531265632816408204102100 

另外,還要注意使用BigDecimal(String) constructor,以避免問題,當您使用double文字創建BigDecimal

4

您應該使用的MathContext作爲劃分爲小數無限多的:

BigDecimal priceDiff = BigDecimal.ONE 
      .subtract(new BigDecimal(9.99) 
      .divide(new BigDecimal(19.99), new MathContext(10, RoundingMode.UP))) 
      .multiply(new BigDecimal(100)); 
    System.out.println(priceDiff.toPlainString()); 

然而,打印50.025 ...

這將打印49.98:

BigDecimal priceDiff = new BigDecimal(9.99) 
     .divide(new BigDecimal(19.99), new MathContext(10, RoundingMode.UP)) 
     .multiply(new BigDecimal(100), new MathContext(4, RoundingMode.UP)); 
System.out.println(priceDiff.toPlainString()); 
1

BigDecimal操作始終嘗試計算精確的結果。嘗試這個。

BigDecimal priceDiff = BigDecimal.ONE 
       .subtract(new BigDecimal(9.99) 
         .divide(new BigDecimal(19.99),RoundingMode.HALF_UP)) 
       .multiply(new BigDecimal(100)); 
     System.out.println(priceDiff.toPlainString()); 
1

類似@ Keppil的回答

double d = (1 - 9.99/19.99) * 100; 
System.out.printf("%.2f%%%n", d); 

打印

50.03% 

你不會得到49.98%,因爲這是不回答您的方程。

+0

是的,我只是對所有這些數字感到困惑:-) – dtrunk

+0

@dtrunk我發現使用'雙'較少混淆。 ;) –

+0

我不能使用double,因爲它會在代碼中造成如此多的變化 – dtrunk

2

Javadoc

在除法的情況下,準確的商可能是一個無限長的十進制擴展;例如,1除以3.如果商具有非終止十進制擴展並且該操作被指定爲返回確切結果,則拋出ArithmeticException。

解決方法是向該部門提供MathContext,例如MathContext.DECIMAL128。如果你想四捨五入做傳統的方式(四捨五入半了,而不是最近的偶數),使用MathContext(int precision)

你也應該創建BigDecimal s的String參數,而不是double參數,因爲精度後者導致損失。