Jerkwin分享 http://blog.sciencenet.cn/u/Jerkwin

博文

一元三次方程求根公式及其Fortran代码

已有 24416 次阅读 2012-10-31 00:10 |个人分类:数学轮子|系统分类:科研笔记| 三次方程

一元三次方程的求解比一元二次方程困难,求根公式看起来也很复杂,中文维基百科上原先的三角函数解公式有误,我已经修改过了。但是我觉得还有必要将这些公式简化一下,给出具体的算法,以便编程使用。


首先需要明确,一元三次方程 $f(x)=ax^3+bx^2+cx+d=0,(aneq0) $ 至少有一个实根。这是由于 $f(-infty)=-infty, f(infty)=infty $,而 $f(x)$ 在整个区间上连续,所以由微积分的介值定理,必存在一点 $x_0$ 满足 $f(x_0)=0$ 。直观上也很容易理解,曲线 $f(x)$ 取值范围为负无穷到正无穷,那么它与x轴至少有一个交点,这个交点就是方程的实根。这个结论可以推广到所有奇数次的多项式方程。

对一元三次方程 $f(x)=ax^3+bx^2+cx+d=0, (aneq0) $ ,首先化为 $f(x)=x^3+{3b over 3a} x^2+{6c over 6a} x+{2d over 2a}=x^3+3b'x^2+6c'x+2d'=0$ 形式,为简便我们仍记作 $f(x)=x^3+3bx^2+6cx+2d=0 $ ,令 $alpha=-b^3+3bc-d, beta=b^2-2c, Delta=alpha^2-beta^3,\ R_1=sqrt[3]{alpha+sqrt{Delta}}, R_2=sqrt[3]{alpha-sqrt{Delta}} $

,则方程的三个根可写作:

$ x_1=-b+R_1+R_2 \ x_2=-b-{(R_1+R_2)over 2} +{sqrt{3}(R_1-R_2) over 2} i \ x_3=-b-{(R_1+R_2) over 2}-{sqrt{3}(R_1-R_2) over 2} i $

其中 $Delta$即为三次方程根的判别式,由其容易看出:

  • $Delta>0$ 时,方程有一个实根 $x_1$ 和两个共轭复根 $x_2$ $x_3$

  • $Delta=0$ 时,有 $R_1=R_2=sqrt[3]{alpha}=R$

    • $Rneq0$ ,方程有一个实根 $x_1=-b+2R$ 和一个二重复根 $x_2=x_3=-b-R$

    • $R=0$ ,方程只有一个三重复根 $x_1=x_2=x_3=-b$      

  • $Delta lt 0 $时,方程有三个不等实根,令 $theta=arccos(     {alpha over beta^{3/2}} ) $ ,则

$x_1=-b+2sqrt{beta} cos( {theta over 3} ) \ x_2=-b+2sqrt{beta} cos( {{theta+2pi} over 3} ) \ x_3=-b+2sqrt{beta} cos( { {theta-2pi} over 3}) $


很显然,$Deltalt 0$ 的情况最复杂,也很让人迷惑,因为实根必须借助于复数才能求得,这也是最初要引入复数的原因。由于我没有学过复变函数,下面的说法可能有误,说出来只是为了帮助大家理解。

$Delta lt 0$ 时,记 $ z=alpha+sqrt{|Delta|}i, bar z=alpha-sqrt{|Delta|}i, R_1=sqrt[3]{z}, R_2=sqrt[3]{bar z} $,若我们认为 $sqrt[3]{bar z}=overline{sqrt[3]{z} } $ ,则 $R_2=bar {R_1} $,记 $ R_1=R,R_2=bar R, omega= { {-1+sqrt{3} i} over 2}, bar omega={ {-1-sqrt{3} i}over 2} $ ,则三个根可写作:

$ x_1=-b+R_1+R_2=-b+R+bar R \x_2=-b-{(R_1+R_2) over 2} +{sqrt{3}(R_1-R_2) over 2} i =-b+omega R+baromega bar R\ x_3=-b-{(R_1+R_2) over 2} -{sqrt{3}(R_1-R_2) over 2} i=-b+bar omega R+ omega bar R $

很显然

$ x_1=-b+2Re(R) \ Re(R)=Resqrt[3]{z} = sqrt[3]{|z|} cos({ {theta+2kpi} over 3}), k=0, 1, -1 \|z|=sqrt{alpha^2+|Delta|}=sqrt{alpha^2-alpha^2+beta^3} = beta^{3/2} \theta = arccos({alpha over |z|}) = arccos({alpha over beta^{3/2}}) $

由于复变函数的多值性,我们一下就得到了所有的三个根,正如上面所给出的。另外由于 $ omega$ 对应的正是旋转 $ 2piover 3 $ 的复数,所以 $ x_2,x_3 $ 并不能给出新的根。

2012-10-31 08:45:32


==============================J*e*r*k*w*i*n*@*g*m*a*i*l*.*c*o*m=============================
 1| Subroutine getCubicRoot(P, X)
 2|     real*8, parameter:: TwoPi = 8.D0*atan(1.D0)
 3|     real*8 P(*), a, b, c, d, Alph, Beta, Delt, R1, R2, tht, X(3)
 4|
 5|     X = 0.D0
 6|     a = P(1)
 7|     b = P(2)/(3.D0*a)
 8|     c = P(3)/(6.D0*a)
 9|     d = P(4)/(2.D0*a)
10|
11|     Alph = -b*b*b + 3.D0*b*c - d
12|     Beta =  b*b - 2.D0*c
13|     Delt = Alph*Alph-Beta*Beta*Beta
14|
15|     if(Delt>0.D0) then
16|         tht = Alph+sqrt(Delt); R1 = sign(abs(tht)**(1.D0/3.D0), tht)
17|         tht = Alph-sqrt(Delt); R2 = sign(abs(tht)**(1.D0/3.D0), tht)
18|         X(1) = -b+R1+R2
19|     else if(Delt==0.D0) then
20|         R1 = sign(abs(Alph)**(1.D0/3.D0), Alph)
21|         if(R1==0.D0) then
22|             X(1) = -b
23|         else
24|             X(1) = -b+2.D0*R1
25|             X(2) = -b-R1
26|         end if
27|     else if(Delt<0.D0) then
28|         tht = acos(Alph/(sqrt(Beta)*Beta))
29|         X(1) = -b+2.D0*sqrt(Beta)*cos(tht/3.D0)
30|         X(2)  = -b+2.D0*sqrt(Beta)*cos((tht+TwoPi)/3.D0)
31|         X(3)  = -b+2.D0*sqrt(Beta)*cos((tht-TwoPi)/3.D0)
32|     end if
33| End Subroutine getCubicRoot
============================================================================================



https://wap.sciencenet.cn/blog-548663-627770.html

上一篇:我的博文编辑器——EmEditor
下一篇:GnuPlot:简单数据统计处理及取整函数int/floor的问题
收藏 IP: 70.166.132.*| 热度|

1 胡力元

该博文允许注册用户评论 请点击登录 评论 (5 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-5-19 05:09

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部