![](/img/trans.png)
[英]Placement of Math.toRadians for solving quadratic and cubic equations
[英]Having trouble solving cubic equations in Java
我正在尝试遵循一些伪代码来解决程序员数学和物理中的三次方程,第 3 章,据我所知,我已经准确地遵循了它,但我似乎没有得到正确的输出。
例如:根据 Wolfram Alpha 5x^3 + 4x^2 + 3x + 2 = 0 应该给出 x≈-0.72932 的根,但我从脚本中返回 -1.8580943294965526。
有人可以帮我弄清楚我在做什么吗? 我正在按照脚本更好地理解数学并将方程式转换为代码。 但这是我理解的边缘,所以我发现调试起来很麻烦。 再加上这本书没有勘误表,而且许多在线评论表明这本书有很多错误,我很难确定问题出在我的代码、书籍解释还是两者兼而有之。
书中给出的等式是:
那么如果判别式 > 0 则 root 的值为 r+s:
如果判别式 == 0 则有两个根:
如果判别式 < 0,您可以找到三个根,如下所示:
找到t后,您可以通过以下方式将其转换为x :
package com.oacc.maths;
public class SolveCubic {
public static double[] solveCubic(double a, double b, double c, double d) {
double[] result;
if (d != 1) {
a = a / d;
b = b / d;
c = c / d;
}
double p = b / 3 - a * a / 9;
double q = a * a * a / 27 - a * b / 6 + c / 2;
double D = p * p * p + q * q;
if (Double.compare(D, 0) >= 0) {
if (Double.compare(D, 0) == 0) {
double r = Math.cbrt(-q);
result = new double[2];
result[0] = 2 * r;
result[1] = -r;
} else {
double r = Math.cbrt(-q + Math.sqrt(D));
double s = Math.cbrt(-q - Math.sqrt(D));
result = new double[1];
result[0] = r + s;
}
} else {
double ang = Math.acos(-q / Math.sqrt(-p * p * p));
double r = 2 * Math.sqrt(-p);
result = new double[3];
for (int k = -1; k <= 1; k++) {
double theta = (ang - 2 * Math.PI * k) / 3;
result[k + 1] = r * Math.cos(theta);
}
}
for (int i = 0; i < result.length; i++) {
result[i] = result[i] - a / 3;
}
return result;
}
public static double[] solveCubic(double a, double b, double c) {
double d = 1;
return solveCubic(a, b, c, d);
}
public static void main(String args[]) {
double[] result = solveCubic(5, 4, 3, 2);
for (double aResult : result) {
System.out.println(aResult);
}
}
}
我还从本书网站上找到了这个代码示例(注意这不是书中的伪代码): http ://www.delmarlearning.com/companions/content/1435457331/files/index.asp?isbn=1435457331
on solveCubic(a,b,c,d)
--! ARGUMENTS:
a, b, c, d (all numbers). d is optional (default is 1)
--!
RETURNS: the list of solutions to dx^3+ax^2+bx+c=0
-- if d is defined then divide a, b and c by d
if not voidp(d)
then
if d=0 then return solveQuadratic(b,c,a)
set d to float(d)
set a to a/d
set b to b/d
set
c to c/d
else
set a to float(a)
set b to float(b)
set c to float(c)
end if
set p to b/3 - a*a/9
set q to a*a*a/27 - a*b/6 + c/2
set disc to p*p*p + q*q
if abs(disc)<0.001 then
set r to cuberoot(-q)
set ret to [2*r, -r]
else if disc>0 then
set r to cuberoot(-q+sqrt(disc))
set s to cuberoot(-q-sqrt(disc))
set ret to [r+s]
else
set ang to acos(-q/sqrt(-p*p*p))
set r to 2*sqrt(-p)
set ret to []
repeat with k=-1 to 1
set theta
to (ang - 2*pi*k)/3
ret.add(r*cos(theta))
end repeat
end if
set ret to ret-a/3 --NB: this adds the value to each
element
return ret
end
该错误似乎与您的solveCubic
方法的参数名称有关。
看来您的书正在解释如何求解方程x 3 + ax 2 + bx + c =0。您在调用方法时认为参数a
, b
, c
和d
用于方程ax 3 + bx 2 + cx + d =0。但是,事实证明,您的方法主体实际上是在寻找方程dx 3 + ax 2 + bx + c = 0的解。
除了此命名错误之外,计算似乎是正确的。 如果您不相信我,请尝试将≈-1.858的值插入2x 3 + 5x 2 + 4x + 3。
如果您改为将您的solveCubic
方法声明为
public static double[] solveCubic(double d, double a, double b, double c) {
然后,这些参数对应于方程dx 3 + ax 2 + bx + c。 然后,您应该发现您的方法可以为您提供期望的答案。
好的。 因此,首先,本书中的方程式似乎是在指这个想法:如果您有以下形式的方程式:
然后通过将t定义为x-(a / 3),您可以将其转换为没有二次项的方程,这已由Mathematica进行了验证:
一旦没有二次项,就可以应用给定的方法; 设q为常数项的一半,设p为第一个幂项的系数的三分之一,并将D (判别式)定义为p*p*p - q*q
。
然后所有其他内容都将遵循。
那么为什么您的代码不起作用? 因为您没有正确标记变量。 a是x^2
而不是x^3
的系数。 如果使用参数(0.8、0.6、0.4、1)或等效地使用(4、3、2、5)调用方法,则将获得正确的答案。
(或者按照其他答案的建议进行操作,并在方法声明中围绕变量名进行更多操作)
公共无效solveCubicEquation(int A,int B,int C,int D){
double a = (double) B / A;
double b = (double) C / A;
double c = (double) D / A;
System.out.println("Double values: ");
System.out.println(a + " " + b + " " + c);
double p = b - ((a * a) / 3.0);
double q = (2 * Math.pow(a, 3) / 27.0) - (a * b / 3.0) + c;
double delta = (Math.pow(q, 2) / 4) + (Math.pow(p, 3) / 27);
if (delta > 0.001) {
double mt1, mt2;
double t1 = (-q / 2.0) + Math.sqrt(delta);
double t2 = (-q / 2.0) - Math.sqrt(delta);
if (t1 < 0) {
mt1 = (-1) * (Math.pow(-t1, (double) 1 / 3));
} else {
mt1 = (Math.pow(t1, (double) 1 / 3));
}
if (t2 < 0) {
mt2 = (-1) * (Math.pow(-t2, (double) 1 / 3));
} else {
mt2 = (Math.pow(t2, (double) 1 / 3));
}
x1 = mt1 + mt2 - (a / 3.0);
} else if (delta < 0.001 && delta > -0.001) {
if (q < 0) {
x1 = 2 * Math.pow(-q / 2, (double) 1 / 3) - (a / 3);
x2 = -1 * Math.pow(-q / 2, (double) 1 / 3) - (a / 3);
} else {
x1 = -2 * Math.pow(q / 2, (double) 1 / 3) - (a / 3);
x2 = Math.pow(q / 2, (double) 1 / 3) - (a / 3);
}
} else {
System.out.println("here");
x1 = (2.0 / Math.sqrt(3)) * (Math.sqrt(-p) * Math.sin((1 / 3.0) * Math.asin(((3 * Math.sqrt(3) * q) / (2 * Math.pow(Math.pow(-p, (double) 1 / 2), 3)))))) - (a / 3.0);
x2 = (-2.0 / Math.sqrt(3)) * (Math.sqrt(-p) * Math.sin((1 / 3.0) * Math.asin(((3 * Math.sqrt(3) * q) / (2 * Math.pow(Math.pow(-p, (double) 1 / 2), 3)))) + (Math.PI / 3))) - (a / 3.0);
x3 = (2.0 / Math.sqrt(3)) * (Math.sqrt(-p) * Math.cos((1 / 3.0) * Math.asin(((3 * Math.sqrt(3) * q) / (2 * Math.pow(Math.pow(-p, (double) 1 / 2), 3)))) + (Math.PI / 6))) - (a / 3.0);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.