gpt4 book ai didi

java - 仅求解四次多项式实根的最有效方法

转载 作者:搜寻专家 更新时间:2023-10-31 20:32:42 26 4
gpt4 key购买 nike

我已经尝试实现一种可以解决给定 a、b、c、d、e 的四次多项式的方法,使用此方法:https://math.stackexchange.com/a/786/127747

它适用于一些有 1 或 2 个实根的解决方案,但问题是,有时所涉及的平方根或立方根可能会导致 NaN 值出现在中间变量中,如果它们将负数作为输入,例如 Math.sqrt(-9),然后与最终答案混淆,使方法末尾的所有根都为 NaN。

在给定变量/系数 a、b、c、d 和 e 的情况下,是否有任何快速分析方法仅获取 Java 中的四次多项式的所有实根,而不涉及一些复杂的库等?

编辑:(任何可理解的语言都可以,但最好是 Java,如果不是这样,我无论如何都会做一个端口,并编辑答案以附加它)

编辑 2:这是我当前的代码,其中 s 是等式中的 p,q 只是稍微优化它的变量,因此相同的计算不会重复两次:

public static double[] solveRealQuarticRoots(double a, double b, double c, double d, double e) {
double s1 = 2 * c * c * c - 9 * b * c * d + 27 * (a * d * d + b * b * e) - 72 * a * c * e,
q1 = c * c - 3 * b * d + 12 * a * e;
s2 = s1 + Math.sqrt(-4 * q1 * q1 * q1 + s1 * s1),
q2 = Math.cbrt(s2 / 2),
s3 = q1 / (3 * a * q2) + q2 / (3 * a),
s4 = Math.sqrt((b * b) / (4 * a * a) - (2 * c) / (3 * a) + s3),
s5 = (b * b) / (2 * a * a) - (4 * c) / (3 * a) - s3,
s6 = (-(b * b * b) / (a * a * a) + (4 * b * c) / (a * a) - (8 * d) / a) / (4 * s4);

double[] roots = new double[4];
for (int i = 0; i < 3; i++)
roots[i] = -b / (4 * a) + (i > 1 ? -1 : 1) * (s4 / 2) - (i % 2 == 0 ? -1 : 1) * (Math.sqrt(s5 + (i > 1 ? -1 : 1) * s6) / 2);

return roots;
}

最佳答案

您可以使用 Descartes' rule of signsSturm's theorem给出根数的上限。可以想象,这可以告诉您期望有多少个根。笛卡尔的规则很快,因为它只涉及比较符号变化。

但是,您可以在当前代码中添加一些分支,以避免出现会导致复杂结果的分支。

public static double[] solveRealQuarticRoots(double a, double b, double c, double d, double e) {
double s1 = 2 * c * c * c - 9 * b * c * d + 27 * (a * d * d + b * b * e) - 72 * a * c * e,
q1 = c * c - 3 * b * d + 12 * a * e;
double discrim1 = -4 * q1 * q1 * q1 + s1 * s1;
if(discrim1 >0) {
double s2 = s1 + Math.sqrt(discrim1);
q2 = Math.cbrt(s2 / 2),
s3 = q1 / (3 * a * q2) + q2 / (3 * a),
discrim2 = (b * b) / (4 * a * a) - (2 * c) / (3 * a) + s3;
if(discrim2>0) {
double s4 = Math.sqrt(discrim2);
double s5 = (b * b) / (2 * a * a) - (4 * c) / (3 * a) - s3;
double s6 = (-(b * b * b) / (a * a * a) + (4 * b * c) / (a * a) - (8 * d) / a) / (4 * s4);
double discrim3 = (s5 - s6),
discrim4 = (s5 + s6);
// actual root values, may not be set
double r1, r2, r3, r4;

if(discrim3 > 0) {
double sqrt1 = Math.sqrt(s5-s6);
r1 = -b / (4 * a) - s4/2 + sqrt1 / 2;
r2 = -b / (4 * a) - s4/2 - sqrt1 / 2;
} else if(discrib3 == 0) {
// repeated root case
r1 = -b / (4 * a) - s4/2;
}
if(discrim4 > 0) {
double sqrt2 = Math.sqrt(s5+s6);
r3 = -b / (4 * a) + s4/2 + sqrt2 / 2;
r4 = -b / (4 * a) + s4/2 - sqrt2 / 2;
} else if(discrim4 ==0) {
r3 = -b / (4 * a) + s4/2;
}
if(discrim3 > 0 && discrim4 > 0)
return {r1,r2,r3,r4};
else if( discrim3 > 0 && discrim4 == 0 )
return {r1,r2,r3};
else if( discrim3 > 0 && discrim4 < 0 )
return {r1,r2};
else if( discrim3 == 0 && discrim4 > 0 )
return {r1,r3,r4};
else if( discrim3 == 0 && discrim4 == 0 )
return {r1,r3};
else if( discrim3 == 0 && discrim4 < 0 )
return {r1};
else if( discrim3 < 0 && discrim4 > 0 )
return {r3,r4};
else if( discrim3 < 0 && discrim4 == 0 )
return {r3};
else if( discrim3 < 0 && discrim4 < 0 )
return new double[0];
}
}
return new double[0];

进一步查看数学交流帖子的答案,其中提到了 Don Herbison-Evans、Michel Daoud Yacoub 和 Gustavo Fraidenraich 的“寻找四次方程的真实根”。你可以找到here .在那篇论文中,他考虑了数值问题。

不要小看数值方法。牛顿速度非常快,可以快速收敛。

关于java - 仅求解四次多项式实根的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37944845/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com