无法弄清楚如何计算四次多项式
Can't figure out how to calculate 4th degree polynomials
我正在尝试创建一个函数来计算包含复数的 4 次多项式的 4 个根。在搜索公式时,我发现了一个相当简单的公式,它包含在 this discussion 中,由 Tito Piezas III 在页面底部描述。
现在,我相信真正的错误并不是我的代码中的错误(因为我确信校对会很烦人),而是我对所涉及方法的理解。我的问题是,二次根很复杂,我不知道如何以编程方式计算四次根时使用复数。
他建议使用两个二次方程的根来推导四次根。我试图用下面的代码尽可能地模仿这个公式。我的想法是,我计算两个二次根(前提是它们只是正数——否则我不知道怎么办),然后,使用这些结果,我可以计算出 qurtic 根,然后保存实数和复数值分别转化为 x1,x2,x3,x4
转化为 r1,r2,r3,r4,c1,c2,c3,c4
。但是,在计算二次根时,u
,后面计算四次根时使用的一个值:是复数!
这是他的公式和步骤的 image。 Blow 是我的代码,大多数步骤都有标题。
double a, b, c, d;
double c1, c2, c3, c4; //complex values
double r1, r2, r3, r4; //real values
// x^4+ax^3+bx^2+cx+d=0
a = 3;
b = 4;
c = 5; //<--- example coefficients
d = 6;
if (a != 0) {
double u,v1,v2;
double x,y,z; //essentially a,b,c that he uses
x=1;
y= -2*b*b*b+9*a*b*c-27*c*c-27*a*a*d+72*b*d;
z= Math.pow((b*b-3*a*c+12*d),3);
//calculation of the v roots
v1 = -y+(Math.sqrt(y*y-4*x*z))/(2*x); // < negative root
v2 = -y-(Math.sqrt(y*y-4*x*z))/(2*x); // < negative root
//---calculations after this are invalid since v1 and v2 are NaN---
u = (a*a)/4 + ((-2*b+Math.pow(v1,1/3)+Math.pow(v2,1/3))/3);
double x12sub,x34sub;
x12sub= 3*a*a-8*b-4*u+((-a*a*a+4*a*b-8*c)/(Math.sqrt(u)));
x34sub= 3*a*a-8*b-4*u-((-a*a*a+4*a*b-8*c)/(Math.sqrt(u)));
r1 = -(1/4)*a +(1/2)*(Math.sqrt(u));
r2 = -(1/4)*a +(1/2)*(Math.sqrt(u));
r3 = -(1/4)*a -(1/2)*(Math.sqrt(u));
r4 = -(1/4)*a -(1/2)*(Math.sqrt(u));
//--casting results into their orderly variables--
if(x12sub<0){
x12sub= x12sub*-1;
x12sub = Math.sqrt(x12sub);
x12sub = x12sub*(1/4);
c1=x12sub;
c2=x12sub;
}
else{
r1=r1+x12sub;
r2=r2-x12sub;
}
if(x34sub<0){
x34sub= x34sub*-1;
x34sub = Math.sqrt(x34sub);
x34sub = x34sub*(1/4);
c3=x34sub;
c4=x34sub;
}
else{
r3=r3+x34sub;
r4=r4+x34sub;
}
}
我愿意接受任何解决方案。即使是那些涉及使用可以帮助我的图书馆的人。感谢您的帮助。
尝试使用高效 Java 矩阵库。您可以在此处下载 jar:https://sourceforge.net/projects/ejml/files/v0.28/
您需要在 class:
中使用此方法
public static Complex64F[] findRoots(double... coefficients) {
int N = coefficients.length-1;
// Construct the companion matrix
DenseMatrix64F c = new DenseMatrix64F(N,N);
double a = coefficients[N];
for( int i = 0; i < N; i++ ) {
c.set(i,N-1,-coefficients[i]/a);
}
for( int i = 1; i < N; i++ ) {
c.set(i,i-1,1);
}
// use generalized eigenvalue decomposition to find the roots
EigenDecomposition<DenseMatrix64F> evd = DecompositionFactory.eig(N,false);
evd.decompose(c);
Complex64F[] roots = new Complex64F[N];
for( int i = 0; i < N; i++ ) {
roots[i] = evd.getEigenvalue(i);
}
return roots;
}
然后你可以用它来求,例如,x^2 + 4x + 4 的根:
Complex64F[] c = findRoots(4, 4, 1);
for(Complex64F f : c)
System.out.println(f.toString());
这将打印出:
-2
-2
这是期望的结果。
你可以使用 sympy a python 模块来解决你的问题。 sympy.solve("any equation")
要么,
如您所知,求多项式的根就是为 X 或其他变量的值找到 0。
像。
X⁴-16=0 有像 2 ,-2 这样的根,所以这里对于 x=2,-2 我得到值 0。所以如果我在某个范围内计算一些 x 值,我们可以找到根。让我们看看 JavaScript 中的代码,它有点慢,但它给出了准确的结果。
equation="x**4-9"
//document.getElementById("equation").value.toLowerCase();
//xxx=document.getElementById("roots")
for(var x=-20;x<=20;x+=0.00001){
var x=parseFloat(x.toFixed(6))
//var x=-0.83333
//var gg="(x**3)+(2*x**2)-(9*x)-18"
cg=eval(equation)
//console.log(x)
//console.log(cg)
if(Math.abs(cg)<0.0002 || cg==0){
roots.add(parseFloat(x.toFixed(4)))
}
}
if(roots.size>=1){
//xxx.innerText=[...roots]+"\n";
console.log([..roots]);
}
else{
alert("this function not convarges")
}
您可以通过变量的线性变化将多项式az^4+bz^3+cz^2+dz+e 消减为t^4+pt^2+qt+r 的形式。然后你分解为 (t^2 + ux + v)(t^2 - ux + w)。这导致识别 p = v + w - u^2, q = u (w - v), r = vw。由此,2w = p + u^2 + q / u,2v = p + u^2 - q / u 最后,(p + u^2 + q / u)(p + u^2 - q / u ) = 4r。重新排列后,这是一个u^2的三次方程。
求解三次az^3+bz^2+cz+d,可以再次耗尽到t^3+pt+q,写成t = u - p / 3u。这给出 u^3 + q - p^3 / 27u^3 = 0,u^3 中的二次方程。
求解一个二次多项式ax^2 + bx + c,可以消减成t^2 + p = 0的形式,根显然是±√(-p)。
因此,您求解 u^3 的二次方程并取其中一个根的立方根。从中,您应用逆耗尽变换并获得三次解。现在你可以计算四次因式的系数,分别求解这两个因数,得到四个根。最后,撤消最初的消耗。
简单,不是吗?
要耗尽多项式,请将所有系数除以前导系数,然后设置 x = t + s。然后代入多项式并展开,就可以抵消第二项的系数。这给出 s = - b / ka 其中 k 是多项式的次数。其他系数来自 s.
对于实系数的多项式,请注意三次方程总是有一个实数解,给出两个二次多项式的因式分解。
无论如何,实系数的三次方的解析可能不可避免地求助于复数。
我正在尝试创建一个函数来计算包含复数的 4 次多项式的 4 个根。在搜索公式时,我发现了一个相当简单的公式,它包含在 this discussion 中,由 Tito Piezas III 在页面底部描述。
现在,我相信真正的错误并不是我的代码中的错误(因为我确信校对会很烦人),而是我对所涉及方法的理解。我的问题是,二次根很复杂,我不知道如何以编程方式计算四次根时使用复数。
他建议使用两个二次方程的根来推导四次根。我试图用下面的代码尽可能地模仿这个公式。我的想法是,我计算两个二次根(前提是它们只是正数——否则我不知道怎么办),然后,使用这些结果,我可以计算出 qurtic 根,然后保存实数和复数值分别转化为 x1,x2,x3,x4
转化为 r1,r2,r3,r4,c1,c2,c3,c4
。但是,在计算二次根时,u
,后面计算四次根时使用的一个值:是复数!
这是他的公式和步骤的 image。 Blow 是我的代码,大多数步骤都有标题。
double a, b, c, d;
double c1, c2, c3, c4; //complex values
double r1, r2, r3, r4; //real values
// x^4+ax^3+bx^2+cx+d=0
a = 3;
b = 4;
c = 5; //<--- example coefficients
d = 6;
if (a != 0) {
double u,v1,v2;
double x,y,z; //essentially a,b,c that he uses
x=1;
y= -2*b*b*b+9*a*b*c-27*c*c-27*a*a*d+72*b*d;
z= Math.pow((b*b-3*a*c+12*d),3);
//calculation of the v roots
v1 = -y+(Math.sqrt(y*y-4*x*z))/(2*x); // < negative root
v2 = -y-(Math.sqrt(y*y-4*x*z))/(2*x); // < negative root
//---calculations after this are invalid since v1 and v2 are NaN---
u = (a*a)/4 + ((-2*b+Math.pow(v1,1/3)+Math.pow(v2,1/3))/3);
double x12sub,x34sub;
x12sub= 3*a*a-8*b-4*u+((-a*a*a+4*a*b-8*c)/(Math.sqrt(u)));
x34sub= 3*a*a-8*b-4*u-((-a*a*a+4*a*b-8*c)/(Math.sqrt(u)));
r1 = -(1/4)*a +(1/2)*(Math.sqrt(u));
r2 = -(1/4)*a +(1/2)*(Math.sqrt(u));
r3 = -(1/4)*a -(1/2)*(Math.sqrt(u));
r4 = -(1/4)*a -(1/2)*(Math.sqrt(u));
//--casting results into their orderly variables--
if(x12sub<0){
x12sub= x12sub*-1;
x12sub = Math.sqrt(x12sub);
x12sub = x12sub*(1/4);
c1=x12sub;
c2=x12sub;
}
else{
r1=r1+x12sub;
r2=r2-x12sub;
}
if(x34sub<0){
x34sub= x34sub*-1;
x34sub = Math.sqrt(x34sub);
x34sub = x34sub*(1/4);
c3=x34sub;
c4=x34sub;
}
else{
r3=r3+x34sub;
r4=r4+x34sub;
}
}
我愿意接受任何解决方案。即使是那些涉及使用可以帮助我的图书馆的人。感谢您的帮助。
尝试使用高效 Java 矩阵库。您可以在此处下载 jar:https://sourceforge.net/projects/ejml/files/v0.28/
您需要在 class:
中使用此方法public static Complex64F[] findRoots(double... coefficients) {
int N = coefficients.length-1;
// Construct the companion matrix
DenseMatrix64F c = new DenseMatrix64F(N,N);
double a = coefficients[N];
for( int i = 0; i < N; i++ ) {
c.set(i,N-1,-coefficients[i]/a);
}
for( int i = 1; i < N; i++ ) {
c.set(i,i-1,1);
}
// use generalized eigenvalue decomposition to find the roots
EigenDecomposition<DenseMatrix64F> evd = DecompositionFactory.eig(N,false);
evd.decompose(c);
Complex64F[] roots = new Complex64F[N];
for( int i = 0; i < N; i++ ) {
roots[i] = evd.getEigenvalue(i);
}
return roots;
}
然后你可以用它来求,例如,x^2 + 4x + 4 的根:
Complex64F[] c = findRoots(4, 4, 1);
for(Complex64F f : c)
System.out.println(f.toString());
这将打印出:
-2
-2
这是期望的结果。
你可以使用 sympy a python 模块来解决你的问题。 sympy.solve("any equation")
要么,
如您所知,求多项式的根就是为 X 或其他变量的值找到 0。
像。
X⁴-16=0 有像 2 ,-2 这样的根,所以这里对于 x=2,-2 我得到值 0。所以如果我在某个范围内计算一些 x 值,我们可以找到根。让我们看看 JavaScript 中的代码,它有点慢,但它给出了准确的结果。
equation="x**4-9"
//document.getElementById("equation").value.toLowerCase();
//xxx=document.getElementById("roots")
for(var x=-20;x<=20;x+=0.00001){
var x=parseFloat(x.toFixed(6))
//var x=-0.83333
//var gg="(x**3)+(2*x**2)-(9*x)-18"
cg=eval(equation)
//console.log(x)
//console.log(cg)
if(Math.abs(cg)<0.0002 || cg==0){
roots.add(parseFloat(x.toFixed(4)))
}
}
if(roots.size>=1){
//xxx.innerText=[...roots]+"\n";
console.log([..roots]);
}
else{
alert("this function not convarges")
}
您可以通过变量的线性变化将多项式az^4+bz^3+cz^2+dz+e 消减为t^4+pt^2+qt+r 的形式。然后你分解为 (t^2 + ux + v)(t^2 - ux + w)。这导致识别 p = v + w - u^2, q = u (w - v), r = vw。由此,2w = p + u^2 + q / u,2v = p + u^2 - q / u 最后,(p + u^2 + q / u)(p + u^2 - q / u ) = 4r。重新排列后,这是一个u^2的三次方程。
求解三次az^3+bz^2+cz+d,可以再次耗尽到t^3+pt+q,写成t = u - p / 3u。这给出 u^3 + q - p^3 / 27u^3 = 0,u^3 中的二次方程。
求解一个二次多项式ax^2 + bx + c,可以消减成t^2 + p = 0的形式,根显然是±√(-p)。
因此,您求解 u^3 的二次方程并取其中一个根的立方根。从中,您应用逆耗尽变换并获得三次解。现在你可以计算四次因式的系数,分别求解这两个因数,得到四个根。最后,撤消最初的消耗。
简单,不是吗?
要耗尽多项式,请将所有系数除以前导系数,然后设置 x = t + s。然后代入多项式并展开,就可以抵消第二项的系数。这给出 s = - b / ka 其中 k 是多项式的次数。其他系数来自 s.
对于实系数的多项式,请注意三次方程总是有一个实数解,给出两个二次多项式的因式分解。
无论如何,实系数的三次方的解析可能不可避免地求助于复数。