将双倍与零比较

我是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.00000000000000001236。

我的问题是,避免这种情况的最佳方法是什么? 我应该检查数字是否介于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."); } } } 

最简单的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."); } 

我应该检查数字是否介于epsilon邻域为零之间?

究竟

这里的解决方案在输入值为整数时是精确的,尽管它可能不是最实用的。

对于具有有限二进制表示的输入值,它可能也可以正常工作(例如,0.125,但不是0.1)。

诀窍:从中间结果中删除所有分区,最后只分割一次。 这是通过跟踪所有(部分)分子和分母来完成的。 如果判别式应为0,那么它的分子将为 0.只要中间加法的值在彼此的约2 ^ 45的范围内(通常是这种情况),就没有舍入误差。

 // Calculate p and q. double pn = 3 * a * c - b * b; double pd = 3 * a * a; double qn1 = 2 * b * b * b; double qd1 = 27 * a * a * a; double qn2 = b * c; double qn3 = qn1 * pd - qn2 * qd1; double qd3 = qd1 * pd; double qn = qn3 * a + d * qd3; double qd = qd3 * a; // Calculate the discriminant. double dn1 = qn * qn; double dd1 = 4 * qd * qd; double dn2 = pn * pn * pn; double dd2 = 27 * pd * pd * pd; double dn = dn1 * dd2 + dn2 * dd1; double dd = dd1 * dd2; discriminant = dn / dd; 

(只检查提供的输入值,所以告诉我是否有问题)

也许BigDecimal值得一看……

http://download.oracle.com/javase/1.4.2/docs/api/java/math/BigDecimal.html

你可以在除法运算中解决圆形模式