C++求解一元三次方程的实根

  • 引言

一元三次方程的解法有多种,百度百科也有介绍,卡尔丹公式盛金公式。我这里主要是用著名的盛金公式解一元三次方程,不得不说盛金公式更为直观性,与我们解一元二次方程很类似。下面就拿来直接用了。

  • 盛金公式

ax^{3}+bx^{2}+cx+d=0(a,b,c,d\in \mathbb{R},a\neq 0)

重根判别式:\left\{\begin{matrix} A=b^{2}-3ac\\ B=bc-9ac\\ C=c^{2}-3bd\\ \end{matrix}\right.,总判别式为:\triangle =B^{2}-4AC。还有四个求根公式详见给的链接,这里就不一一写出了。

  • 代码实现

  • C++

从上可以看出,转成C++/matlab很容易实现,但是注意C++判断一个数(float)等于0不能用==0,而是用<1e-6,所有有时候会有一些很小的误差。下面我给出我的实现函数ShengJin,调用即可。注意这里我只取出了实根。

void ShengJin(double a,double b,double c,double d,vector<double> &X123)
{
	/************************************************************************/
	/* 盛金公式求解三次方程的解 
	   德尔塔f=B^2-4AC
           这里只要了实根,虚根需要自己再整理下拿出来
	*/
	/************************************************************************/
	double A=b*b-3*a*c;
	double B=b*c-9*a*d;
	double C=c*c-3*b*d;
	double f=B*B-4*A*C;
	double i_value;
	double Y1,Y2;
	if (fabs(A)<1e-6 && fabs(B)<1e-6)//公式1
	{
		X123.push_back(-b/(3*a));
		X123.push_back(-b/(3*a));
		X123.push_back(-b/(3*a));
	}
	else if (fabs(f)<1e-6)   //公式3
	{
		double K=B/A;
		X123.push_back(-b/a+K);
		X123.push_back(-K/2);
		X123.push_back(-K/2);
	}
	else if (f>1e-6)      //公式2
	{
		Y1=A*b+3*a*(-B+sqrt(f))/2;
		Y2=A*b+3*a*(-B-sqrt(f))/2;
		double Y1_value=(Y1/fabs(Y1))*pow((double)fabs(Y1),1.0/3);
		double Y2_value=(Y2/fabs(Y2))*pow((double)fabs(Y2),1.0/3);
		X123.push_back((-b-Y1_value-Y2_value)/(3*a));//虚根我不要
		//虚根还是看看吧,如果虚根的i小于0.1,则判定为方程的一根吧。。。
		i_value=sqrt(3.0)/2*(Y1_value-Y2_value)/(3*a);
		if (fabs(i_value)<1e-1)
		{
			X123.push_back((-b+0.5*(Y1_value+Y2_value))/(3*a));
		}
	}
	else if (f<-1e-6)   //公式4
	{
		double T=(2*A*b-3*a*B)/(2*A*sqrt(A));
		double S=acos(T);
		X123.push_back((-b-2*sqrt(A)*cos(S/3))/(3*a));
		X123.push_back((-b+sqrt(A)*(cos(S/3)+sqrt(3.0)*sin(S/3)))/(3*a));
		X123.push_back((-b+sqrt(A)*(cos(S/3)-sqrt(3.0)*sin(S/3)))/(3*a));
	}
}

这里参照博客matlab实现一元三次方程来验证代码。

  • matlab

matlab有自带的函数多项式求解函数:roots 求解一元三次方程。

x=roots([a, b, c, d]);
for k=1:length(x)
    xx(k) = isreal(x(k));%求实根
end
X_real=x(xx); %X_real都是实根

当然,matlab也有大佬实现了盛金公式求解一元三次方程,可以参考这篇博客,写的很详细:盛金公式matlab版

  • 总结

在编写求解代码时,也看过和实践过别人的求解代码,很多都是用基于一次二次导数的二分法来求解方程(我还有一份,需要的可以私信我),较为复杂且费时。因此参照盛金公式进行了编写C++代码,网上肯定也有同类代码,思想都一样的,很多时候我们为了求解一元三次方程并不是实验,而是为了达到我们的研究目的,比如我这只要实根。

要在C++求解一元三次方程,你可以使用牛顿迭代或者高斯-赛德尔迭代等数值方。以下是一个使用牛顿迭代求解一元三次方程的示例代码: ```cpp #include <iostream> #include <cmath> double func(double x, double a, double b, double c, double d) { return a * pow(x, 3) + b * pow(x, 2) + c * x + d; } double derivative(double x, double a, double b, double c) { return 3 * a * pow(x, 2) + 2 * b * x + c; } double newtonMethod(double a, double b, double c, double d, double initialGuess, double epsilon, int maxIterations) { double x = initialGuess; int iteration = 0; while (fabs(func(x, a, b, c, d)) > epsilon && iteration < maxIterations) { x = x - func(x, a, b, c, d) / derivative(x, a, b, c); iteration++; } return x; } int main() { double a, b, c, d; std::cout << "Enter coefficients a, b, c and d of the cubic equation: "; std::cin >> a >> b >> c >> d; double initialGuess; std::cout << "Enter initial guess for the root: "; std::cin >> initialGuess; double epsilon; std::cout << "Enter epsilon (tolerance): "; std::cin >> epsilon; int maxIterations; std::cout << "Enter maximum number of iterations: "; std::cin >> maxIterations; double root = newtonMethod(a, b, c, d, initialGuess, epsilon, maxIterations); std::cout << "Root: " << root << std::endl; return 0; } ``` 在此示例中,我们使用牛顿迭代来寻找方程的根。用户需要输入方程的系数a、b、c、d,以及初始猜测值、容差和最大迭代次数。程序将输出找到的根。 请注意,这只是一个简单的示例,并且不一定适用于所有情况。在实际应用中,您可能需要考虑处理方程无解或多个解的情况,并对算进行更多的优化和错误处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值