[英]Double subtraction precision issue
我的同事做了这个实验:
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会失败? 如果 double 不是这项工作的数据类型,我应该使用什么?
double
在内部存储为二进制的分数——比如1/4 + 1/8 + 1/16 + ...
值0.005
-- 或值1.435
-- 不能存储为二进制的精确分数,因此double
不能存储精确值0.005
,并且减去的值不是很精确。
如果您关心精确的十进制算术,请使用BigDecimal
。
您可能还会发现 这篇文章很有用。
double 和 float不完全是实数。
在任何范围内都有无限数量的实数,但只有有限数量的位来表示它们! 出于这个原因,双精度和浮点数预计会出现舍入误差。
您得到的数字是最接近的数字,可以用浮点表示中的 double 表示。
有关更多详细信息,您可能需要阅读 这篇文章[警告:可能是高级别的]。
您可能想要使用BigDecimal
来精确地获得一个十进制数 [但是当您尝试获得1/3
时,您将再次遇到舍入错误]。
由于“幕后”发生的舍入, double
和float
算法永远不会完全正确。
本质上双精度和浮点数可以有无限数量的小数,但在内存中它们必须由一些实数表示。 因此,当您执行此十进制算术时,会发生舍入过程,并且如果您将所有小数都考虑在内,通常会偏离很小的数量。
如前所述,如果您需要完全精确的值,则使用BigDecimal
以不同方式存储其值。 这是 API
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
//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();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.