给定一个数A,不使用sqrt函数,求A的开方,要求精度大于0.0001
该题有两种方法求解:①牛顿迭代法;②二分法
①牛顿迭代法:
1.牛顿迭代法知识:
牛顿迭代法(Newton's method)又称为牛顿-拉夫逊方法(Newton-Raphson method),它是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法。多数方程不存在求根公式,因此求精确根非常困难,甚至不可能,从而寻找方程的近似根就显得特别重要。方法使用函数f(x)的泰勒级数的前面几项来寻找方程f(x) = 0的根。牛顿迭代法是求方程根的重要方法之一,其最大优点是在方程f(x) = 0的单根附近具有平方收敛,而且该法还可以用来求方程的重根、复根。另外该方法广泛用于计算机编程中。
设r是f(x) = 0的根,选取x0作为r初始近似值,过点(x0,f(x0))做曲线y = f(x)的切线L,L的方程为y = f(x0)+f'(x0)(x-x0),求出L与x轴交点的横坐标 x1 = x0-f(x0)/f'(x0),称x1为r的一次近似值。
过点(x1,f(x1))做曲线y = f(x)的切线,并求该切线与x轴交点的横坐标 x2 = x1-f(x1)/f'(x1),称x2为r的二次近似值。重复以上过程,得r的近似值序列,其中x(n+1)=x(n)-f(x(n))/f'(x(n))(公式1),称为r的n+1次近似值,上式称为牛顿迭代公式。
2.本题迭代公式推导
因为本题的题目是求开方,设待求开方的值为A,而开方后的值为x,则A与x的关系为A=x2,即求函数f(x)=x2-A=0的根。再根据上述的公式(1)即x(n+1)=x(n)-f(x(n))/f'(x(n)),将f(x),f”(x)带入公式得到x(n+1) = x(n)-(x2-A)/2x=x(n)+(A/x- x)/2。
迭代公式:X(n+1)=X(n)+(A/X(n)-X(n))/2,其中A是输入的待求被开方的数,X(n)是一次与A的开方相近的数,X(n+1)是下一次与A的开方相近的数 。
同理可以得到开三次放的迭代公式X(n+1)=Xn+(A/X^2-Xn)1/3 ,A、X(n)、X(n+1)意义与开平方相同。
①输入初始值X(0),最简单的是将X(0)定为1
②通过迭代公式计算与A相近的下一个开方数X(n),直到|A-X(n)|<0.001为止。
#include<iostream> using namespace std; double MySqrt(double A,double precision) //A为待开方的数,precision为精度 { if(A<0) throw"不能为负数!"; double X=1; while(abs(A-X*X)>precision) { X = X +(A/X-X)/2; } return X; } | int main() { double a; cout<<"输入一个不小于0的数"; cin>>a; cout<<MySqrt(a,0.001)<<endl; return 0; }
|
②牛顿二分法
一般地,对于函数f(x),如果存在实数c,当x=c时,若f(c)=0,那么把x=c叫做函数f(x)的零点。
解方程即要求f(x)的所有零点。
假定f(x)在区间(x,y)上连续
先找到a、b属于区间(x,y),使f(a),f(b)异号,说明在区间(a,b)内一定有零点,然后求f[(a+b)/2],
①如果f[(a+b)/2]=0,该点就是零点,
如果f[(a+b)/2]<0,则在区间((a+b)/2,b)内有零点,(a+b)/2>a,从①开始继续使用
中点函数值判断。
如果f[(a+b)/2]>0,则在区间(a,(a+b)/2)内有零点,(a+b)/2<b,从①开始继续使用
中点函数值判断。
这样就可以不断接近零点。
通过每次把f(x)的零点所在小区间收缩一半的方法,使区间的两个端点逐步迫近函数的零点,以求得零点的近似值,这种方法叫做二分法。
#include<iostream> using namespace std; double MySqrt(double A,double precision)//二分法 { if(A<0) throw "不能为负数!"; double min =0,max = A; double result = (min+max)/2; while(abs(A-result*result)>precision) { if(A-result*result>0) min =result; else max = result; result =(min+max)/2; } return result; }
| int main() { double a; cout<<"输入一个不小于0的数"; cin>>a; cout<<MySqrt(a,0.001)<<endl; return 0; }
|