一元三次方程求解

 a*x^3+b*x^2+c*x+d=0

枚举+二分

#include<cstdio>
#include<cmath>
#include<cstdlib>
using namespace std;
const double PI = acos(-1.0);
double a,b,c,d;
double R,m;
double f(double x)
{
    return a*x*x*x+b*x*x+c*x+d;
}
//解一元三次方程组 a*x^3+b*x^2+c*x+d=0 ,解的上下界为min_ans,max_ans
double solve(double a,double b,double c,double d,double min_ans,double max_ans)
{
	double x,x1,x2,xx;
	for (x=min_ans; x<=max_ans; x+=1)
    {
        x1=x;
        x2=x+1;
        if(f(x1)==0)//有解
        {
            if(x1>=0)//判断是否为正数
            {
            	//x1为解
                printf("%.2f ",2*R-x1);
                return 0;
            }
        }
        else if (f(x1)*f(x2)<0)
        {
        	double l=x1,r=x2;
            while (r-l>=0.0001)
            {
                double mid=(r+l)/2;
                if ((f(l)*f(mid))<=0)
                    r=mid;
                else
                    l=mid;
            }
            if(l>=0)
            {
            	//l为解
                printf("%.2f ",2*R-l);
                return 0;
            }
        }
    }
}
int main()
{
  
    scanf("%lf%lf",&R,&m);
    a=PI;
    b=-3*PI*R;
    c=0;
    d=(3)*m;
    solve(a,b,c,d,-100,100);
    return 0;

    
}

盛金公式(求三个根)

 

 

《一元三次方程求解》

 

①:当A=B=0时,方程有一个三重实根;

  ②:当Δ=B2-4AC>0时,方程有一个实根和一对共轭虚根;

  ③:当Δ=B2-4AC=0时,方程有三个实根,其中有一个两重根;

  ④:当Δ=B2-4AC<0时,方程有三个不相等的实根。

 

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cctype>
#include<cstring>
#include<utility>
#include<cstdlib>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define Clear(x) memset(x,0,sizeof(x))
#define fup(i,a,b) for(int i=a;i<b;i++)
#define rfup(i,a,b) for(int i=a;i<=b;i++)
#define fdn(i,a,b) for(int i=a;i>b;i--)
#define rfdn(i,a,b) for(int i=a;i>=b;i--)
typedef long long ll;
using namespace std;
const int maxn = 1e+2;
const int inf = 0x3f3f3f3f;
const double pi=acos(-1.0);
const double eps = 1e-3;
double a,b,c,d;
/**
盛金公式
*/
 
int main()
{
    double x1,x2,x3,temp;
    scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
    double A=b*b-3*a*c;
    double B=b*c-9*a*d;
    double C=c*c-3*b*d;
    double del=B*B-4*A*C;
    //Δ=B2-4AC>0时是虚根
    if(A==B&&A==0)
    {
        x1=x2=x3=-b/(3*a);
    }else if(del==0){
        x1=-b/a+B/A;
        x2=x3=(-B/A)/2;
    }else if(del<0){
        double T=(2*A*b-3*a*B)/(2*A*sqrt(A));
        double _xt=acos(T);
        double xt=_xt/3;
        x1=(-b-2*sqrt(A)*cos(xt))/(3*a);
        x2=(-b+sqrt(A)*(cos(xt)+sqrt(3)*sin(xt)))/(3*a);
        x3=(-b+sqrt(A)*(cos(xt)-sqrt(3)*sin(xt)))/(3*a);
    }
    printf("%.2lf %.2lf %.2lf\n",x1,x2,x3);
    return 0;
}

牛顿迭代法(求三个根)

首先 f(x)=ax3+bx2+cx+d 求导得到 df/dx=3ax2+2bx+c
求这个导数的零点(就是二次函数求根公式了)得到f(x)的最值点
最值点组成的三个区间一定各有一个f(x)零点,使用牛顿迭代法求得这个零点即可
牛顿迭代法就是不停的用一个点的切线拟合曲线,那个点的导数就是切线斜率

依次类推,可以得到求高次函数零点的一种迭代法:
求n次函数零点,需要极值点来划分区间,也就需要求其导数(n-1次函数)的零点,依次迭代到n=2直接通过公式(当然n=3或4也可以)
最后的复杂度依赖于求零点算法的复杂读

 



#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps=1e-3;
double a,b,c,d;
inline double f(double x){return ((a*x+b)*x+c)*x+d;}
inline double df(double x){return (3*a*x+2*b)*x+c;}
double sol(double l,double r){//printf("sol %lf %lf\n",l,r);
    int step=20;double x=(l+r)/2;
    while(step--){
        x=x-f(x)/df(x);
    }
    return x;
}
int main(int argc, const char * argv[]) {
    scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
    double p1=(-sqrt(b*b-3*a*c)-b)/(3*a),
    p2=(+sqrt(b*b-3*a*c)-b)/(3*a);
    printf("%.2f %.2f %.2f\n",sol(-100,p1),sol(p1,p2),sol(p2,100));
    return 0;
}

卡尔丹公式

百度百科

韦达定理

由代数基本定理加上数学归纳法可推出其能分解成a(x-x1)(x-x2)(x-x3)的形式(x1,x2,x3∈复数域)

x1x2x3=-(d/a)

x1x2+x2x3+x1x3=c/a

x1+x2+x3=-b/a

这就是三次方程时的韦达定理

 

    原文作者:pxlsdz
    原文地址: https://blog.csdn.net/sdz20172133/article/details/102622042
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞