我是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.");
}
}
}
答案 0 :(得分:17)
最简单的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.");
}
答案 1 :(得分:14)
我应该检查这个数字是否介于epsilon附近 为零?
完全
答案 2 :(得分:4)
这里的解决方案在输入值为整数时是精确的,尽管它可能不是最实用的。
对于具有有限二进制表示的输入值,它可能也会正常工作(例如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;
(仅检查提供的输入值,所以告诉我是否有错误)
答案 3 :(得分:3)
也许BigDecimal
值得一看......
http://download.oracle.com/javase/1.4.2/docs/api/java/math/BigDecimal.html
您可以在除法运算中隐藏循环模式