float compare
Abstract
使用float数据进行精确计算和比较,可能由于精度问题导致程序逻辑异常。
Explanation
使用float数据进行比较,计算机表达double和float型数据其实是个近似值,而不是精确值,直接用
它们进行比较判断,得到的结果可能与预期完全不同,导致程序逻辑异常。最严重的情况是进行相等
性比较"=="和"!=",极易错误;其次是">=""<="等比较判断,也比较容易出错。
示例1 double型数据进行判断。
public static double integral(MyFunction f, double x1, double x2) { double x = x1; double result = 0; double step = (x2 - x1) / 700; while (x != x2) { // 可以改为 (x ﹤= x2) result = result + f.valueFor(x) * step; x = x + step; } return result; }
上述代码可能导致无限的循环,因为由于计算的误差,x!=x2,可能永远是成立的。
示例2 double型数据进行判断。
public static final double MAX_MONEY=0.2; public string test(double d1,double d2){ double d3=d1+d2;// if(d3<=MAX_MONEY){ return "OK"; } }
上述代码,当d1=d2=0.1时,d3=0.20000000149011612是>0.2的,程序员想当然以为d3<=MAX_MONEY是
成立的,进行了错误的处理逻辑。
Recommendation(解决办法)
1、进行大于或等于、小于或等于,或小于某值的不同绝对值的检查,例如 Math.abs(x1-x2) ﹤MIN_DIFF;
bool float_equals(float a,float b){ if (abs(a-b)<=1e-6) return true; return false; }
2、根据场景可以考虑采用整数类型或用于精确表达小数的BigDecimal类型替代。