为什么在Java中对两个BigDecimal数字进行除法运算会抛出ArithmeticException异常?

10
让我们来看一下Java中的以下代码片段。
package division;

import java.math.BigDecimal;

final public class Main
{
    public static void main(String[] args)
    {
        BigDecimal a = new BigDecimal(2);
        BigDecimal b = new BigDecimal(3);

        System.out.println(a.multiply(b));
        System.out.println(a.add(b));
        System.out.println(b.subtract(a));
        System.out.println(a.divide(b));
    }
}

在上面的代码片段中,除了最后一个操作(除法)之外,所有操作都成功执行。在Java中尝试将两个BigDecimal数字相除会抛出java.lang.ArithmeticException异常。为什么?如何解决这个问题?

2
看起来和这个很像:https://dev59.com/xXE85IYBdhLWcg3wgDlI - dexametason
4个回答

19

根据BigDecimal#divide(BigDecimal)文档

......如果不能表示准确的商(因为它具有非终止的十进制数扩展形式),则会抛出一个ArithmeticException异常。

在您的特定情况下,"2/3"具有非终止的十进制数扩展形式(0.6666...),因此您必须使用一种带有比例和/或RoundingModedivide()形式来解决无限表示问题。例如:

BigDecimal a = new BigDecimal(2);
BigDecimal b = new BigDecimal(3);
a.divide(b, 4, RoundingMode.CEILING); // => 0.6667
a.divide(b, 4, RoundingMode.FLOOR);   // => 0.6666

2

您之所以会遇到异常,是因为除法的结果没有精确的表示方式。为了解决这个问题,您需要使用带有比例和舍入模式的重载方法,像这样:

System.out.println(a.divide(b, 20, RoundingMode.HALF_UP));

这里是您在ideone上修改后的代码链接

6
5
1
0.66666666666666666667

1

如果你读javadoc,它会告诉你当精确商没有终止小数时会抛出java.lang.ArithmeticException异常。2/3=.666666666...是无限循环的,因此不会终止。


1
返回一个BigDecimal,其值为(this / divisor),首选标度为(this.scale() - divisor.scale())。如果无法表示精确的商(因为它具有非终止的小数扩展),则抛出ArithmeticException异常。
2/3=0.666666666666666666666……等等,它无法表示。正如JavaDoc所说,这是一种非终止的小数扩展。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接