由于在二进制表示中存储这些值的挑战,浮点数学是不精确的。更糟糕的是,浮点数学不是关联的; 推动float
或double
通过一系列简单的数学运算,由于每个步骤发生的舍入,答案将根据这些操作的顺序而不同。
即使是简单的浮点赋值也不简单:
float f = 0.1; // 0.100000001490116119384765625
double d = 0.1; // 0.1000000000000000055511151231257827021181583404541015625
(结果将根据编译器和编译器设置而有所不同);
因此,在值或值上使用equality(==
)和inequality(!=
)运算符几乎总是一个错误。相反,最好的方法是完全避免浮点比较。如果不可能,您应该考虑使用Java的浮点处理之一,例如可以正确处理浮点比较。第三种选择是不要考虑相等性,而是考虑价值是否足够接近。即,将存储值和期望值之间的差的绝对值与可接受误差的余量进行比较。请注意,这并不能掩盖所有的情况下(和 为实例)。float
double
Numbers
BigDecimal
NaN
Infinity
此规则检查浮点数和双精度数的直接和间接相等/不等于测试的使用。
不合规的代码示例
float myNumber = 3.146;
if(myNumber == 3.146f){//不合规。由于浮点不精确,这将是假的
... ...
}
if(myNumber!= 3.146f){//不合规。由于浮点不精确,这将是真的
// ...
}
如果(myNumber <4 || myNumber> 4){//不合规; 间接不等式检验
// ...
}
float zeroFloat = 0.0f;
if(zeroFloat == 0){//不合规。计算可能最终得到一个接近但不等于零的值。
}
解决方法
两实数相等:两实数的差在允许的范围内认为相等既可认为是相等的。
范围:1e-6(0.000001)
主要代码:
boolean IsEqual(double a,double b)
{
//计算机表示浮点数(float或double类型)都有一个精度限制,对于超出了精度限制的浮点数,计算机会把它们的精度之外的小数部分截断。因此,本来不相等的两个浮点数在计算机中可能就变成相等的了
//因此一般不会直接用“==”或者“!=”对两个浮点数进行比较。判断两个浮点数是否相等可以根据他们的差的绝对值是否大于0来进行判断。
//考虑到实际应用,一般如果两个浮点数之差的绝对值小于或等于某一个可接受的误差(即精度,比如0.00000001即可),就认为它们是相等的。
return Math.abs(a-b) < 0.000001;
}