6

可能重复:
在 BigDecimal.divide 期间引发 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());
4

5 回答 5

10

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)构造函数以避免在BigDecimal使用double文字创建时出现问题。

于 2012-08-29T12:39:01.890 回答
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());
于 2012-08-29T12:39:15.693 回答
2

Javadoc

在除法的情况下,精确商可以有一个无限长的小数展开;例如,1 除以 3。如果商具有非终止十进制扩展并且指定操作返回精确结果,则会引发 ArithmeticException。

解决方案是提供一个MathContext给分部,例如MathContext.DECIMAL128. 如果您想以传统方式进行舍入(向上舍入而不是最接近的偶数),请使用MathContext(int precision)

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

于 2012-08-29T12:44:15.193 回答
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());
于 2012-08-29T12:42:20.547 回答
1

类似于@Keppil的回答

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

印刷

50.03%

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

于 2012-08-29T12:43:33.293 回答