这导致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());
答案 0 :(得分:9)
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)
constructor来避免在使用BigDecimal
字面值创建double
时出现问题。
答案 1 :(得分: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());
答案 2 :(得分:2)
来自Javadoc:
在除法的情况下,精确商可以具有无限长的十进制扩展;例如,1除以3.如果商具有非终止十进制扩展并且指定了操作以返回精确结果,则抛出ArithmeticException。
解决方案是向分部提供MathContext
,例如MathContext.DECIMAL128
。如果你想要以传统的方式完成舍入(舍入一半而不是最接近的偶数),请使用MathContext(int precision)
您还应该使用BigDecimal
参数而不是String
参数创建double
,因为后者会导致精度损失。
答案 3 :(得分: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());
答案 4 :(得分:1)
类似于@Keppil的回答
double d = (1 - 9.99 / 19.99) * 100;
System.out.printf("%.2f%%%n", d);
打印
50.03%
你不会得到49.98%,因为这不是你方程式的答案。