ArithmeticException:"非终止十进制扩展;没有可精确表示的十进制结果"

Jas*_*son 480 java bigdecimal arithmeticexception

为什么以下代码会引发下面显示的异常?

BigDecimal a = new BigDecimal("1.6");
BigDecimal b = new BigDecimal("9.2");
a.divide(b) // results in the following exception.
Run Code Online (Sandbox Code Playgroud)

-

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
Run Code Online (Sandbox Code Playgroud)

DVK*_*DVK 804

来自Java 8文档:

当MathContext对象的精度设置为0时(例如,MathContext.UNLIMITED),算术运算是精确的,算术方法也不是MathContext对象.(这是5之前版本中唯一支持的行为.)

作为计算精确结果的必然结果,不使用精度设置为0的MathContext对象的舍入模式设置,因此不相关.在除法的情况下,精确商可以具有无限长的十进制扩展; 例如,1除以3.

如果商具有非终止十进制扩展并且指定了操作以返回精确结果,则抛出ArithmeticException.否则,返回除法的确切结果,与其他操作一样.

要修复,你需要做这样的事情:

a.divide(b, 2, RoundingMode.HALF_UP)

where 2 is scale and RoundingMode.HALF_UP is rounding mode
Run Code Online (Sandbox Code Playgroud)

更多细节:http://jaydeepm.wordpress.com/2009/06/04/bigdecimal-and-non-terminating-decimal-expansion-error/

  • 2不是'精度'; 这是"规模".请参阅http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#divide%28java.math.BigDecimal,%20int,%20java.math.RoundingMode%29 (26认同)
  • 我不认为他需要`toPlainString`. (2认同)
  • 这也适用于jasper错误,谢谢http://community.jaspersoft.com/questions/528968/help-please-adding-two-double-values#comment-807628 (2认同)

Dav*_*ock 74

因为您没有指定精度和舍入模式.BigDecimal抱怨它可以使用10,20,000,或无限小数位,但它仍然无法准确表示数字.因此,它不会给你一个不正确的BigDecimal,它只会对你产生影响.

但是,如果你提供一个RoundingMode和一个精度,那么它将能够转换(例如1.333333333到无穷大到类似于1.3333 ...但是你作为程序员需要告诉它你对'满意'的准确度".


Min*_*ain 52

你可以做

a.divide(b, MathContext.DECIMAL128)
Run Code Online (Sandbox Code Playgroud)

您可以选择所需的位数32,64,128.

看看这个链接:

http://edelstein.pebbles.cs.cmu.edu/jadeite/main.php?api=java6&state=class&package=java.math&class=MathContext


小智 14

为了解决这个问题我在下面的代码中使用过

a.divide(b, 2, RoundingMode.HALF_EVEN)
Run Code Online (Sandbox Code Playgroud)

2是精度.现在问题解决了.

  • 2不是'精度'; 这是"规模".请参阅http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#divide%28java.math.BigDecimal,%20int,%20java.math.RoundingMode%29 (10认同)
  • 除了代码之外,还应该提供一些解释. (3认同)
  • 对于财务应用程序,建议使用RoundingMode.HALF_EVEN.这就是银行业所使用的 (3认同)

小智 7

这是一个舍入结果的问题,我的解决方案如下。

\n\n
divider.divide(dividend,RoundingMode.HALF_UP);\n
Run Code Online (Sandbox Code Playgroud)\n


小智 6

我有同样的问题,因为我的代码行是:

txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");
Run Code Online (Sandbox Code Playgroud)

我改为这个,阅读之前的答案,因为我没有写小数精度:

txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");
Run Code Online (Sandbox Code Playgroud)

4是Decimal Precion

AND RoundingMode是Enum常量,您可以选择其中任何一个 UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP

在这个案例HALF_UP中,将得到以下结果:

2.4 = 2   
2.5 = 3   
2.7 = 3
Run Code Online (Sandbox Code Playgroud)

您可以在RoundingMode此处查看以下信息:http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/