划分BigDecimals会导致ArithmeticException

时间:2012-08-29 12:32:37

标签: java math

  

可能重复:
  ArithmeticException thrown during BigDecimal.divide

这导致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());

5 个答案:

答案 0 :(得分: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来避免在使用BigDecimal字面值创建double时出现问题。

答案 1 :(得分: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());

答案 2 :(得分:2)

来自Javadoc

  

在除法的情况下,精确商可以具有无限长的十进制扩展;例如,1除以3.如果商具有非终止十进制扩展并且指定了操作以返回精确结果,则抛出ArithmeticException。

解决方案是向分部提供MathContext,例如MathContext.DECIMAL128。如果你想要以传统的方式完成舍入(舍入一半而不是最接近的偶数),请使用MathContext(int precision)

您还应该使用BigDecimal参数而不是String参数创建double,因为后者会导致精度损失。

答案 3 :(得分: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());

答案 4 :(得分:1)

类似于@Keppil的回答

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

打印

50.03%

你不会得到49.98%,因为这不是你方程式的答案。