在 Java 中,如果语句为真,为什么此代码 return 为假?看起来不像是浮点错误,打印时的值是相等的

In Java, why does this code return a false if the statement is true? Doesn't seem like a floating point error and the values when printed are equal

我正在测试一个我想知道的随机公式。在编写代码来测试公式后,大多数是正确的,但有些是错误的。然而,我注意到在我的 print 语句中,等式的两边是相等的,但代码说它们不是。

代码如下:

public static void main(String[] args){
        for(int i = 0; i < 100; i++){
            String t = runTest((100-i)/100.0,i/100.0);
            if(t.substring(0, 1).equals("1")) System.err.println(t);
            else System.out.println(t.substring(1));
        }
    }

    private static String runTest(double a, double b){
        double l = (a + b);
        double r = (a*a + b*b + 2*a*b);
        boolean isValid = false;
        if(l != 1) {
            return 1+String.format("%f + %f = %f\tInvalid", a, b, a + b);
        }
        if(l==r){
            isValid = true;
        }

        return 0+String.format("A: %f B: %f LEFT: %f RIGHT: %f RESULT: %s", a, b, l, r, String.valueOf(isValid));
    }

我也尝试过将 l 和 r 转换为整数,r returns 0 有时意味着代码认为 r 小于 0。实际上和 print 语句,右侧也是 1 . 一开始以为是浮点数错误,结果两边都是1.

你知道为什么会这样吗?我该如何解决这个问题?

谢谢。

运行 这个

public class Test {
public static void main(String[] args){
    for(int i = 0; i < 100; i++){
        String t = runTest((100-i)/100.0,i/100.0);
        if(t.substring(0, 1).equals("1")) System.err.println(t);
        else System.out.println(t.substring(1));
    }
}

private static String runTest(double a, double b){
    double l = (a + b);
    double r = (a*a + b*b + 2*a*b);
    boolean isValid = false;
    if(l != 1) {
        //return 1+String.format("%f + %f = %f\tInvalid", a, b, a + b);
        return  a + ":" + b+ ":" +  a  +  b ;
    }
    if(l==r){
        isValid = true;
    }
    return  a + ":" + b+ ":" +  l + ":" +  r ;
 }

}

所以是的,当格式化为浮点数时它们看起来相等,但它们是双精度数(64 位),这就是您比较它们的方式(因此它们不相等,正如您从我发布的代码输出中看到的那样) .

使用 == 运算符比较浮点数是否相等是 bad practise.

您必须包含公差。

final float T = 0.0000001;
if (Math.abs(l - r) < T)
  isValid = true;

修改 T 使其符合您的需要。