方程求根的几种数值方法--求解x^3 - x -1 = 0


方程求根的几种数值方法--求解x^3 - x -1 = 0

求非线性方程的根主要有基本的二分法、迭代法。迭代法中设计到对于基本迭代算法的改进:Aitken加速法,牛顿迭代法。

首先初始工作,函数的构造

//简单迭代函数构造
double CFunction(double x) 
{ 
	x = x + 1;
	double y = pow(x, 0.3333333);		//计算机中没有1/3和0这样的数,用近似数代替
	return y;
}

//Aitken迭代函数构造
double CFunction_1(double x)
{
	double y = x * x;
	y = y * x - 1;
	return y;
} 
//二分法函数构造
double tFunction(double x)
{
	double y = x * x;
	y = y * x - x - 1;
	return y;
}

//判断区间有无根,只适用于区间较小时,和特定函数
double JuRoot(double tFunction(double x), double a, double b)
{
	return tFunction(a) * tFunction(b);
}

double ReturnJust(double tFunction(double x), double upper, double below)
{
	double result = 0;
	if((result = JuRoot(tFunction, upper, below)) > 1E-6) 
		return 0;
	else
	return 1;  
}

二分法的基本思想:一分为二,舍去不满足条件的部门,这个条件便是零点定理。

算法实现:E1:f(x_1) * f( x_2) <0,是,转到E2;否则无解

                  E2:middle = (x_1+x_2)/2,分别判断左右两支是否满足E1,满足跳转E3

                  E3:x_? = middle,赋值满足的一方,跳转E1

代码实现如下:

//二分法设计
double FindRoot(double tFunction(double x), double &upper, double &below)
{  
	double result = 0;
	
	if((result = ReturnJust(tFunction, upper, below)) == 0) 
		{
		   cout << "嘿,没有搞错吧,居然没有根" << endl;
		   return 0;
	    }
	    
	double middle = (upper + below) / 2;
	
	if(abs(upper - below) > 1E-6)
	{
	if((result = JuRoot(tFunction, upper, middle)) < 1E-6)
	{
		below = middle;
		count ++;
		return FindRoot(tFunction, upper, below);
	}
	else 
	{
		upper = middle;
		count ++;
		return FindRoot(tFunction, upper, below);
	}
    }
    
	return upper;
}

简单迭代算法的思想:将f(x)=0,改写成x=g(x)的形式。然后在区间[a,b]上任取一点x_0,求得x_1 = g(x_0),一直迭代下去,x_k+1 = g(x_k).由极限的思想可知,当x_k+1收敛到x*时,则g(x)收敛到g(x*)。当然在选取x_0的时候可以 用二分法算出大致的根,进行迭代更好。

对于简单迭代,构造函数时要使得函数的一阶导数递减,否则容易导致发散,而找不到所要的根。

//简单迭代
double FindRoot_2(double CFunction(double x), double upper, double below, double &x)
{
	double result = 0;

	if((result = ReturnJust(tFunction, upper, below)) == 0) 
		{
		   cout << "嘿,没有搞错吧,居然没有根" << endl;
		   return 0;
	    }
	double i = CFunction(x);

	if(abs(i - x) > 1E-6)
		{
			x = i;
			count ++;
			return FindRoot_2(CFunction, upper, below, x);
		}
	else 
		return x;

	cout << "真不巧,这里找不到你想要精度的根" << endl;
	return 0;
}


Aitken加速法是简单迭代算法的加速,迭代公式:

(1)x_k+1 = g(x_k);

(2)x_k+2 = g(x_k+1)

(3)x = x_k+2 - (x_k+2 - x_k+1)^2/(x_k+2 -2*x_k+1 + x_k) 


//AITKEN迭代
double FindRoot_3(double CFunction_1(double x), double upper, double below, double &x)
{
	double result = 0;

	if((result = ReturnJust(tFunction, upper, below)) == 0) 
		{
		   cout << "嘿,没有搞错吧,居然没有根" << endl;
		   return 0;
	    }
	    
	double x_1, x_2, x_3, i, j;
	x_1 = CFunction_1(x);
	x_2 = CFunction_1(x_1);
	i = (x_2 - x_1) * (x_2 - x_1);
	j = (x_2 - 2 * x_1 + x);
	x_3 = x_2 - (i / j);
	
	if(abs(x_3 - x_2) > 1E-6)
		{
			x = x_3;
			//cout << x_1 << endl;
			count ++;
			return FindRoot_3(CFunction_1, upper, below, x);
		}
	else 
		return x;
		
	cout << "真不巧,这里找不到你想要精度的根" << endl;
	return 0;
} 

牛顿迭代思想:g(x) = x - f(x)/f'(x),利用的是函数在某点的切线与x轴的交点近似代替函数与x轴的交点.

其中变形有:弦割法,牛顿下山法,抛物线法


#include<iostream>
#include<cmath>
double s(double t)
{
	return t-(t*t*t-t-1)/(3*t*t-1);
}
using namespace std;
int main()
{
	int i;
	double x,x0,x1,x2,e;
	cout<<"请输入迭代初始值x0"<<",和控制精度e"<<endl;
cin >>x0>>e;
i=0;
x1=x0;
while(fabs(s(x1)-x1)>e)
{
	i++;
	x2=s(x1);
	x1=x2;
}
x=(x1+x2)/2;
cout<<"近似根x="<<x<<endl;
		cout<<"所需迭代次数i="<<i<<endl;
		return 0;
}

#include<iostream>
#include<cmath>
double s(double t)
{
	return  t*t*t-t-1;
}
using namespace std;
int main()
{
	int i;
	double x,x0,x1,x2,e;
	cout<<"请输入迭代初始值x0,x1"<<",和控制精度e"<<endl;
cin >>x0>>x1>>e;
i=0;
while(fabs(x1-x0)>e)
{
i++;
x2=x1-s(x1)*(x1-x0)/(s(x1)-s(x0));
x0=x1;
x1=x2;
}
x=(x1+x2)/2;
cout<<"近似根x="<<x<<endl;
		cout<<"所需迭代次数i="<<i<<endl;
		return 0;
}




  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值