不适用Sqrt函数开方,精度小于指定精度

22 篇文章 0 订阅
15 篇文章 1 订阅

给定一个数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,则Ax的关系为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)<0,f(b)>0,a<b  

①如果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;

}

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值