一元三次方程求解(求根) - 盛金公式法
一、引言
只含有一個未知數(即“元”),並且未知數的最高次數爲3(即“次”)的整式方程叫做一元三次方程(英文名:cubic equation in one unknown)。一元三次方程的標準形式(即所有一元三次方程經整理都能得到的形式)是ax3+bx2+cx+d=0(a,b,c,d爲常數,x爲未知數,且a≠0)。一元三次方程的公式解法有卡爾丹公式法。(--引自百度百科);
由於卡爾丹公式法和多項式求解的方法不容易理解,不容易用程序實現,經過文獻的查找了解到盛金公式求解一元三次方程,經驗證求根正確可以引用。
二、盛金公式簡介
80年代,中國中學數學教師範盛金對解一元三次方程問題進行了深入的研究和探索,發明了比卡爾丹公式更適用的新根公式 - 盛金公式,並建立了簡明的、直觀的、使用的新判別法 - 盛金判別法,同時提出了盛金定理;盛金定理清晰地回答瞭解一元三次方程的疑惑問題,並且很有趣味。
盛金公式的特點是由最簡重根判別式:, , ;和總判別式來構成,體現了數學的有序、對稱、和諧與簡潔美。
三、盛金公式表達式
- 一元三次方程式爲:
(1)
- 重根判別式爲:
(2)
- 總判別式爲:
(3)
- 盛金判別法的結論爲:
1. 條件一: 當A = B = 0時,方程有一個三重實根
(4)
2. 條件二: 當 時 ,方程有一個實根和一個共軛虛根
(5)
其中:
;
3. 條件三:當時,方程有三個實根,其中有一個兩重根
(6)
其中:
;
4. 條件四: 當時,方程有三個不相等的實根
(7)
其中:
四、盛金公式求解程序流程
五、java和matlab實例代碼
-
matlab代碼
function x = solve3Polynomial(a, b, c, d)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% funtion x = solve3Polynomial(a, b, c, d)
%
%> @brief 利用盛金公式求解三階多項式的解.
%>
%> @details 輸入三階多項式係數,求解ax^3 + bx^2 + cx^1 + d = 0的根
%> 參考文獻:範盛金. 一元三次方程的新求根公式與新判別法[J]. 海南師範學院學報,1989,2(2):91-98.
%>
%> @param[out] x 求解完成的三個根x1,x2,x3
%> @param[in] a 三次項係數
%> @param[in] b 二次項係數
%> @param[in] c 一次項係數
%> @param[in] d 零次項係數
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 重根判別式
A = b*b - 3*a*c; if abs(A) < 1e-14; A = 0; end
B = b*c - 9*a*d; if abs(B) < 1e-14; B = 0; end
C = c*c - 3*b*d; if abs(C) < 1e-14; C = 0; end
%% 總判別式
DET = B*B - 4*A*C; if abs(DET) < 1e-14; DET = 0; end
%% 條件一
if (A == 0) && (B == 0)
x1 = -c/b; x2 = x1 ; x3 = x1;
end
%% 條件二
if DET > 0
Y1 = A*b + 1.5*a*(-B + sqrt(DET));
Y2 = A*b + 1.5*a*(-B - sqrt(DET));
y1 = nthroot(Y1,3); y2 = nthroot(Y2,3);
x1 = (-b-y1-y2)/(3*a);
vec1 = (-b + 0.5*(y1 + y2))/(3*a);
vec2 = 0.5*sqrt(3)*(y1 - y2)/(3*a);
x2 = complex(vec1, vec2);
x3 = complex(vec1, -vec2);
clear Y1 Y2 y1 y2 vec1 vec2;
end
%% 條件三
if DET == 0 && (A ~= 0) && (B ~= 0)
K = (b*c-9*a*d)/(b*b - 3*a*c); K = round(K,14);
x1 = -b/a + K; x2 = -0.5*K; x3 = x2;
end
%% 條件四
if DET < 0
sqA = sqrt(A);
T = (A*b - 1.5*a*B)/(A*sqA);
theta = acos(T);
csth = cos(theta/3);
sn3th = sqrt(3)*sin(theta/3);
x1 = (-b - 2*sqA*csth)/(3*a);
x2 = (-b + sqA*(csth + sn3th))/(3*a);
x3 = (-b + sqA*(csth - sn3th))/(3*a);
clear sqA T theta csth sn3th;
end
x = [x1; x2; x3];
end
-
java代碼
public double solve3Polynomial(double a, double b, double c, double d)
{
double x1 = 0.0, x2 = 0.0, x3 = 0.0;
double A = 0.0, B = 0.0 , C =0.0 , DET = 0.0;
// 1. 計算重根判別式
A = b*b - 3*a*c;
if(Math.abs(A) < 1e-14)
{
A = 0.0;
}
B = b*c - 9*a*d;
if(Math.abs(B) < 1e-14)
{
B = 0.0;
}
C = c*c - 3*b*d;
if(Math.abs(C) < 1e-14)
{
C = 0.0;
}
// 2. 計算總判別式
DET = B*B - 4*A*C;
if(Math.abs(DET) < 1e-14)
{
DET = 0;
}
// 3. 條件一,計算根
if((A == 0) && (B == 0))
{
x1 = (-1*c)/b;
x2 = x1;
x3 = x1;
//Log.i("roots", "條件一:" + x1 );
}
// 4. 條件二,計算根
if(DET > 0)
{
double Y1 = A*b + 1.5*a*(-1*B + Math.sqrt(DET));
double Y2 = A*b + 1.5*a*(-1*B - Math.sqrt(DET));
//Log.i("SQSddd", "Y1: " + Y1 + " Y2: " + Y2);
double y1 = getCubeRoot(Y1);
double y2 = getCubeRoot(Y2);
x1 = (-1.0*b-(y1+y2))/(3.0*a); // 一個實根
double vec1 = (-1*b + 0.5*(y1 + y2))/(3*a);
double vec2 = 0.5*Math.sqrt(y1 - y2)/(3*a);
// x2 = Math.
double x3_real = 0.0, x2_real = 0.0; // 實部
x2_real = (-b + getCubeRoot(Y1)) / (3 * a);
x3_real = x2_real;
double x2_virtual = 0.0, x3_virtual = 0.0; // 虛部
x2_virtual = ((Math.sqrt(3) / 2) * (y1 - y2 )) / (3 * a);
x3_virtual = -x2_virtual;
//Log.i("roots", "條件二:" + x1 );
}
// 5. 條件三,計算根
if(DET == 0 && A != 0 && B != 0)
{
double K = (b*c - 9*a*d)/(b*b -3*a*c);
K = Math.round(K);
x1 = (-1.0*b)/a + K;
x2 = -1*0.5*K;
x3 = x2;
//Log.i("roots", "條件三:" + x1 );
}
// 6.條件四,計算根
if(DET < 0)
{
double sqA = Math.sqrt(A);
double T = (A*b - 1.5*a*B)/(A*sqA);
double theta = Math.acos(T);
double csth = Math.cos(theta/3);
double sn3th = Math.sqrt(3)*Math.sin(theta/3);
x1 = (-1*b - 2*sqA*csth)/(3*a);
x2 = (-1*b + sqA*(csth + sn3th))/(3*a);
x3 = (-1*b + sqA*(csth - sn3th))/(3*a);
//Log.i("SQSd", "條件四:" + x1 );
}
// 7. 返回計算結果
return x1;
}
public double getCubeRoot(double value) {
if (value < 0) {
return -Math.pow(-value, 1.0/3.0);
} else if (value == 0) {
return 0;
} else {
return Math.pow(value, 1.0/3.0);
}
}