/**
對(duì)分法求非線性方程的根
算法思想:在區(qū)間[a,b]間找到所有根,從a開始搜尋,步長(zhǎng)h.
對(duì)每一個(gè)子區(qū)間[xi ,xi+1], xi+1 = xi +h:
1.若f(xi) = 0, xi為實(shí)根,從xi +h/2 繼續(xù)搜索2.若f(xi+1) = 0, xi+1為實(shí)根, 從 xi+1+h/2 繼續(xù)搜索
3..若f(xi) f(xi+1) >0, 當(dāng)前子區(qū)間無實(shí)根, 從xi+1繼續(xù)搜索
4...若f(xi) f(xi+1) <0, 當(dāng)前子區(qū)間有實(shí)根 ,二分搜索尋找根(當(dāng)然,只能找到一個(gè)根)
注意步長(zhǎng)h的選擇, 過大導(dǎo)致漏根, 過小導(dǎo)致計(jì)算量增大.
《數(shù)值計(jì)算方法與算法》-2 Editon -科學(xué)出版社 P86
《C#數(shù)值計(jì)算算法編程》 p207
代碼維護(hù):2007.04.20 pengkuny
**/
#include<iostream>
#include<cmath>
using namespace std;
#define epsilon 0.00001 //精度
double func(double x)//方程表達(dá)式

{
double y;
y = (((((x-5)*x+3)*x+1)*x-7)*x+7)*x-20; //范例方程,6次方程,至多六個(gè)實(shí)根
return y;
}

/**//**
nNumRoots:實(shí)根個(gè)數(shù)的預(yù)估值
x[]:記錄搜索到的所有實(shí)根,
xStart: 區(qū)間的左端點(diǎn)
xEnd : 區(qū)間的右端點(diǎn)
Step : 搜索求根時(shí)采用的步長(zhǎng)
返回:求得的實(shí)根的數(shù)目
*/
int getRootBisect(int nNumRoots, double x[], double xStart, double xEnd, double Step)

{
int n,js;
double z,y,z1,y1,z0,y0;
// 根的個(gè)數(shù)清0
n = 0; 
// 從左端點(diǎn)開始搜索
z = xStart;
y = func(z);
// 循環(huán)求解
while ((z<=xEnd+Step/2.0) && (n!=nNumRoots))
{
if (fabs(y)<epsilon)
{
n++;
x[n-1] = z;
z = z+Step/2.0;
y = func(z);
}
else
{
z1 = z+Step;
y1 = func(z1);
if (fabs(y1)<epsilon)
{
n++;
x[n-1]=z1;
z=z1+Step/2.0;
y=func(z);
}
else if (y*y1>0.0)
{
y=y1;
z=z1;
}
else
{
js=0;//是否找到根的標(biāo)志
while (js==0)
{
if (fabs(z1-z)<epsilon)
{
n++;
x[n-1]=(z1+z)/2.0;
z=z1+Step/2.0; y=func(z);
js=1;
}
else//對(duì)分搜索
{
z0=(z1+z)/2.0;
y0=func(z0);
if (fabs(y0)<epsilon)
{
x[n]=z0;
n++;
js=1;
z=z0+Step/2.0;
y=func(z);
}
else if ((y*y0)<0.0)
{
z1=z0;
y1=y0;
}
else 
{
z=z0;
y=y0;
}
}
}
}
}
}
// 返回實(shí)根的數(shù)目
return(n);
}
int main()

{
cout<<"對(duì)分法求解非線性方程:"<<endl;
double a = -2.5, b = 5;
double *x= new double[6];
int n = getRootBisect(6, x, a, b, 0.2);
cout<<"共有"<<n<<"個(gè)根:"<<endl;
for (int i =0; i<n; i++)
{
cout<<" "<<x[i];
}
cout<<endl;
system("pause");
return 0;
}
