ArithmeticException:“非终止十进制扩展; 没有确切的可表示的小数结果“

为什么下面的代码会引发如下所示的exception?

BigDecimal a = new BigDecimal("1.6"); BigDecimal b = new BigDecimal("9.2"); a.divide(b) // results in the following exception. 

 java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. 

从Java 5文档( 这里是 Java 8文档):

如果提供MathContext对象的精度设置为0(例如,MathContext.UNLIMITED),则算术运算是精确的,不包括MathContext对象的算术方法也是如此。 (这是在5之前的版本中唯一支持的行为。)

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

如果商有一个非终止的十进制扩展,并且操作被指定为返回一个确切的结果,则抛出一个ArithmeticException。 否则,返回分割的确切结果,如同其他操作一样。

要解决,你需要做这样的事情

 a.divide(b, 2, RoundingMode.HALF_UP) where 2 is precision and RoundingMode.HALF_UP is rounding mode 

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

因为你没有指定精度和舍入模式。 BigDecimal抱怨说它可以使用10,20,5000或无穷小数位,但它仍然无法给出数字的确切表示。 所以不是给你一个不正确的BigDecimal,它只是呜咽着你。

然而,如果你提供了一个RoundingMode和一个精度,那么它将能够转换(例如1.333333333到无穷大到1.3333这样的东西…但是你作为程序员需要告诉它你精确度是多么的高兴”。

你可以做

 a.divide(b, MathContext.DECIMAL128) 

你可以select你想要的位数32,64,128。

看看这个链接:

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

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

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

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

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

 txtTotalInvoice.setText(var1.divide(var2).doubleValue() + ""); 

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

 txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + ""); 

4是十进制Precion

AND RoundingMode是枚举常量,你可以select这个UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP

在这种情况下,HALF_UP将会有这样的结果:

 2.4 = 2 2.5 = 3 2.7 = 3 

你可以在这里查看RoundingMode信息: http : //www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/

BigDecimal的答案抛出ArithmeticException

 public static void main(String[] args) { int age = 30; BigDecimal retireMentFund = new BigDecimal("10000.00"); retireMentFund.setScale(2,BigDecimal.ROUND_HALF_UP); BigDecimal yearsInRetirement = new BigDecimal("20.00"); String name = " Dennis"; for ( int i = age; i <=65; i++){ recalculate(retireMentFund,new BigDecimal("0.10")); } BigDecimal monthlyPension = retireMentFund.divide( yearsInRetirement.divide(new BigDecimal("12"), new MathContext(2, RoundingMode.CEILING)), new MathContext(2, RoundingMode.CEILING)); System.out.println(name+ " will have £" + monthlyPension +" per month for retirement"); } public static void recalculate (BigDecimal fundAmount, BigDecimal rate){ fundAmount.multiply(rate.add(new BigDecimal("1.00"))); } 

在除法方法调用中添加MathContext对象并调整精度和舍入模式。 这应该解决您的问题

这是因为Bigdecimal没有丢失,如果你将1/3分开,就会导致重复小数到无穷大。 0.33333333 …理论上如果你乘以返回,你会收到确切的结果。 但是无限数字将产生堆栈溢出,在这种情况下,exception被启动。

我的解决scheme

  try { result = n1.divide(n2); } catch (ArithmeticException e){ Log.d("Error bigdecimal", e.toString()); result = (n1.doubleValue()/n2.doubleValue()); }; 

在这种情况下,你的结果不会被四舍五入