为什么以下代码会引发下面显示的异常?
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.
答案 0 :(得分:763)
来自Java 8文档:
当MathContext对象的精度设置为0时(for 例如,MathContext.UNLIMITED),算术运算是精确的,如 是不采用MathContext对象的算术方法。 (这是 仅在5.)之前的版本中支持的行为。
作为计算确切结果的必然结果,MathContext的舍入模式设置 不使用精度设置为0的对象,因此无关紧要。在 在除法的情况下,精确的商可以具有无限长的小数 扩张;例如,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/
答案 1 :(得分:72)
因为您没有指定精度和舍入模式。 BigDecimal抱怨它可以使用10,20,000,或无限小数位,但它仍然无法准确表示数字。因此,它不会给你一个不正确的BigDecimal,它只会对你产生影响。
但是,如果你提供一个RoundingMode和一个精度,那么它将能够转换(例如1.333333333到无穷大到类似1.3333 ...但你作为程序员需要告诉它你是多么精确'满意'。
答案 2 :(得分:47)
你可以做到
a.divide(b, MathContext.DECIMAL128)
您可以选择所需的位数32,64,128。
点击此链接:
答案 3 :(得分:13)
为了解决这个问题,我使用了以下代码
a.divide(b, 2, RoundingMode.HALF_EVEN)
2是精确的。现在问题解决了。
答案 4 :(得分:6)
我遇到了同样的问题,因为我的代码行是:
txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");
我改为这个,阅读之前的答案,因为我没有写小数精度:
txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");
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
您可以在此处查看RoundingMode
信息:http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
答案 5 :(得分:2)
这是对结果进行四舍五入的问题,以下是我的解决方案。
divider.divide(dividend,RoundingMode.HALF_UP);
答案 6 :(得分:1)
回答BigDecimal throws 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")));
}
在divide方法调用中添加MathContext对象并调整精度和舍入模式。这应该可以解决您的问题
答案 7 :(得分:1)
对我来说,它可以解决这个问题:
new String(configuration.Quote, 2)
答案 8 :(得分:0)
这是因为Bigdecimal没有丢失,例如,如果你除以1/3,它将导致重复的十进制到无穷大。 0.33333333 ...理论上如果你再乘以,你会得到确切的结果。但是,无穷大数字将生成堆栈溢出流,在这种情况下启动异常。
解决方案:
try {
result = n1.divide(n2);
} catch (ArithmeticException e){
Log.d("Error bigdecimal", e.toString());
result = (n1.doubleValue() / n2.doubleValue());
};
或
n1.divide(n2,RoundingMode.HALF_UP);
在这种情况下,您的结果不会被舍入
切断答案 9 :(得分:0)
您的程序不知道使用十进制数字的精度,所以它会抛出:
springfox
java.lang.ArithmeticException: Non-terminating decimal expansion