二分算法求非线性方程的根(单根)
#include <iostream>
using namespace std;
#include <math.h>
double Bisection(double x0, double x1, double eps1, double eps2, int* pBis, double (*funcptr)(double));
//二分法,x0和x1是区间端点,
//eps1是自变量误差界,eps2是函数误差界,funcptr指向函数,(*pBis)记录对分次数
//f(x),返回值是方程的解,如果边值选取不当,返回0;
double func(double x)//所求方程f(x) = 0中的f(x)函数
{
return ( pow(x, 6) - x - 1 );
}
int main()
{
int n = 0; //记录对分次数
double x = 0; //记录解
x = Bisection (1, 2, 0.0001, 0.0001, &n, func); //func前加取地址号&也可以
printf("经过%d次对分,得到解为%lf/n", n, x);
cout<<"经过"<<n<<"次对分,得到解为:"<<x<<endl;
return 0;
}
double Bisection (double x0, double x1, double eps1, double eps2, int* pBis, double (*funcptr)(double))
{
double f0, f1; //保存f(x0)和f(1)的返回值
double f, x; //保存函数和自变量的运算中间值
f0 = (*funcptr)(x0);
f1 = (*funcptr)(x1);
//检查f(x0)和f(1)是否同号
if(f0 * f1 > 0)
{
cout <<"边界选取不当,x0和x1的函数值同号!"<<endl;
return 0;
}
//检查函数值是否小于函数误差界eps2,如果是,证明已取到解
if(fabs(f0)<eps2) return x0;
if(fabs(f1)<eps2) return x1;
(*pBis) = 0;
//循环对分,直到获得解
while(++(*pBis))
{
x = (x0 + x1) / 2;
//检查x是否满足小于自变量误差界,如果是,返回x作为解
if( fabs(x1-x) < eps1*fabs(x1) ) return x;
f = (*funcptr)(x);
//检查函数值是否小于函数误差界eps2,如果是,返回x作为解
if(fabs(f) < eps2) return x;
//对分区间
if(f1 * f < 0)
{
x0 = x;
f0 = f;
}
else
{
x1 = x;
f1 = f;
}
}
return 0;//防止意外错误,最后置一个返回
}
/*
本程序的优缺点:
优点:简单,收敛性好
缺点:无法重根,无法求复根;收敛数度不快
*/