将双精度值与零进行比较

2022-09-02 12:12:36

我是Java的新手,我一直在尝试实现一种算法来查找三次方程的根。当我计算判别式并尝试检查它相对于零的位置时,问题就出现了。

如果运行它并输入数字“1 -5 8 -4”,则输出如下所示:

1 -5 8 -4
p=-0.333333, q=0.074074
disc1=0.001372, disc2=-0.001372
discriminant=0.00000000000000001236
Discriminant is greater than zero.

我知道问题出现了,因为双精度的计算并不精确。通常,判别式应该是0,但它最终是0.0000000000000000001236。

我的问题是,避免这种情况的最佳方法是什么?我应该检查这个数字是否落在 epsilon 邻域为零之间吗?还是有更好,更精确的方法?

提前感谢您的回答。

import java.util.Scanner;

class Cubical {
    public static void main(String[] args) {
        // Declare the variables.
        double a, b, c, d, p, q, gamma, discriminant;

        Scanner userInput = new Scanner(System.in);
        a = userInput.nextDouble();
        b = userInput.nextDouble();
        c = userInput.nextDouble();     
        d = userInput.nextDouble();

        // Calculate p and q.
        p = (3*a*c - b*b) / (3*a*a);
        q = (2*b*b*b) / (27*a*a*a) - (b*c) / (3*a*a) + d/a;

        // Calculate the discriminant.
        discriminant = (q/2)*(q/2) + (p/3)*(p/3)*(p/3);

        // Just to see the values.
        System.out.printf("p=%f, q=%f\ndisc1=%f, disc2=%f\ndiscriminant=%.20f\n", p, q, (q/2)*(q/2), (p/3)*(p/3)*(p/3), (q/2)*(q/2) + (p/3)*(p/3)*(p/3));

        if (discriminant > 0) {
            System.out.println("Discriminant is greater than zero.");
        }
        if (discriminant == 0) {
            System.out.println("Discriminant is equal to zero.");
        }
        if (discriminant < 0) {
            System.out.println("Discriminant is less than zero.");
        }
    }
}

答案 1

最简单的 epsilon 检查是

if(Math.abs(value) < ERROR)

更复杂的一个与值成正比

if(Math.abs(value) < ERROR_FACTOR * Math.max(Math.abs(a), Math.abs(b)))

在您的特定情况下,您可以:

if (discriminant > ERROR) {
    System.out.println("Discriminant is greater than zero.");
} else if (discriminant < -ERROR) {
    System.out.println("Discriminant is less than zero.");
} else {
    System.out.println("Discriminant is equal to zero.");
}

答案 2

我应该检查这个数字是否落在 epsilon 邻域为零之间吗?

完全


推荐