我的同事做了这个实验:
public class DoubleDemo {
public static void main(String[] args) {
double a = 1.435;
double b = 1.43;
double c = a - b;
System.out.println(c);
}
}
对于这个一年级的操作,我期待这个输出:
0.005
但出乎意料的是输出是:
0.0050000000000001155
为什么在这么简单的操作中双重失败?如果double不是这项工作的数据类型,我应该使用什么?
答案 0 :(得分:19)
double
内部存储为二进制中的分数 - 例如1/4 + 1/8 + 1/16 + ...
值0.005
- 或值1.435
- 无法以二进制形式存储为精确分数,因此double
无法存储精确值0.005
,并且减去的值不太准确。
如果您关心精确的十进制算术,请使用BigDecimal
。
您还可以找到this article有用的阅读材料。
答案 1 :(得分:2)
double和float 不完全是实数。
在任何范围内都有无限数量的实数,但只有有限数量的位来表示它们!因此,对于double和float,预计会出现舍入错误。
您获得的数字是可以用双点浮点表示法表示的最接近的数字。
有关详细信息,您可能需要阅读this article [警告:可能是高级别的]。
您可能希望使用BigDecimal
来获取十进制数字[但是当您尝试获取1/3
]时,您将再次遇到舍入错误。
答案 2 :(得分:1)
double
和float
算术永远不会完全正确,因为“引擎盖下”会发生舍入。
基本上双精度和浮点数可以有无限的小数,但在内存中它们必须由一些实数位表示。因此,当您执行此十进制算术时,会发生舍入过程,如果考虑所有小数,则通常会关闭非常小的数量。
如前所述,如果您需要完全准确的值,请使用BigDecimal
以不同方式存储其值。 Here's the API
答案 3 :(得分:0)
是的,它使用BigDecimal操作就是这样
private static void subtractUsingBigDecimalOperation(double a, double b) {
BigDecimal c = BigDecimal.valueOf(a).subtract(BigDecimal.valueOf(b));
System.out.println(c);
}
答案 4 :(得分:0)
public class BigDecimalExample {
public static void main(String args[]) throws IOException {
//floating point calculation
double amount1 = 2.15;
double amount2 = 1.10;
System.out.println("difference between 2.15 and 1.0 using double is: " + (amount1 - amount2));
//Use BigDecimal for financial calculation
BigDecimal amount3 = new BigDecimal("2.15");
BigDecimal amount4 = new BigDecimal("1.10") ;
System.out.println("difference between 2.15 and 1.0 using BigDecimal is: " + (amount3.subtract(amount4)));
}
}
输出:
使用 double 的 2.15 和 1.0 之间的差异是:1.0499999999999998 使用 BigDecmial 的 2.15 和 1.0 之间的区别是:1.05
答案 5 :(得分:-1)
//just try to make a quick example to make b to have the same precision as a has, by using BigDecimal
private double getDesiredPrecision(Double a, Double b){
String[] splitter = a.toString().split("\\.");
splitter[0].length(); // Before Decimal Count
int numDecimals = splitter[1].length(); //After Decimal Count
BigDecimal bBigDecimal = new BigDecimal(b);
bBigDecimal = bBigDecimal.setScale(numDecimals,BigDecimal.ROUND_HALF_EVEN);
return bBigDecimal.doubleValue();
}