牛顿迭代法求平方根

来源:互联网 发布:修改机顶盒mac地址 编辑:程序博客网 时间:2024/04/28 00:41

直接进入主题,打开计算器平方根到底是怎么计算的,一直是我心里的一个疑问,从上初中学了根号以后,老师就让我背根号2等于1.41,根号三是1.732,其他的不用记,题目出现会在后面告诉你。那么这些数字到底是怎么来的呢?首先来看一下牛顿迭代法求平方根的过程。


    如图,是求根号3的牛顿迭代法过程。这里使用的初始迭代值(也就是猜测值)为1,其实可以为任何值最终都能得到结果。来说一下迭代法的过程,每次开始,先检测猜测值是否合理,不合理时,用上面的平均值来换掉猜测值,依次继续迭代,直到猜测值合理。

    再来分析一下这个迭代法的原理。现在取一个猜测值 a,   如果猜测值合理的话,那么就有a^2=x,即x/a=a  ,x为被开方数。不合理的话呢,就用表中的猜测值和商的平均值来换掉猜测值。当不合理时,比如 a>真实值,那么x/a<真实值,这时候取a 与 x/a 的平均值来代替a的话,那么新的a就会比原来的a要更接近真实值。同理有 a<真实值 的情况。于是,这样不断迭代下去最终是一个a不断收敛到真实值的一个过程。于是不断迭代就能得到真实值,证明了迭代法是正确的。

    那么,最终我们需要一个检验猜测值是否正确,只需要  |a^2-x|<ε即可。 在我下面的程序里面,对这个检验做了一些改进,因为若是开方数是一个特别小的值,比如纳米级的单位,那么这种检验很明显不再适用。于是,我做了归一化处理,用之前的猜测值a1与之后的猜测值a2做差再比上之前的猜测值<ε。这样便消弱了量纲带来的影响。

下面是我的c++程序:


#include <iostream>using std::cout;using std::endl;  double improve(double guess, double  x){      return (guess + (x / guess)) / 2;} bool IsOK(double guess, double guess2){      if (abs(guess - guess2)/guess2 <0.001)           return true;      else           return false;} double MySqrt2(double guess, double x){      if (IsOK(guess,improve(guess, x) ) )          //检测猜测值是否足够           return guess;      else           return MySqrt2(improve(guess, x), x);      //否则继续迭代} double MySqrt(double x){      returnMySqrt2(1, x);} int main(){      int a=3;      cout <<MySqrt(a) << endl;      system("pause()");      return 0;}

其实说到这里,我还有些话想说。关于这个程序朋友也编了一个


double MySqrt3(double x, double y1 ){//y1 is start point;double y2 = y1;///y2 is next point;do{if (abs(y1)<1e-6){printf("y1 is 0");return 0;}y1 = y2;y2 = (y1 + x / y1) / 2;printf("y1:%f,y2:%f\n", y1, y2);} while (abs(y2 - y1)>0.0001);return y2;} 

    对比两个程序,明显我的程序要长一些,看起来复杂一些。因为我的程序是纯面向过程的。

    自从学了c++以后,第一次接触面向对象的概念,总觉得这个家伙特别的高大上,同时把它当做了c与c++的一个区别。听过其他老师讲的课,每次也特别强调c语言是一个纯面向过程的语言。其实现在感觉到,面向过程还是面向对象其实不需要区分的那么明显,不过是两种不同的编程思想而已。我们这个世界都是辩证统一的,没有什么东西是绝对的,编程也一样。不管是面向对象还是面向过程,它们应该是有交互点的。比如编写面向对象的程序,里面有的东西我也可以用面向过程的方式来编写。

    一直以来,编程最吸引我的地方就是它很自由,充满了无限的创造性。我想,它在这方面也应该是这样的。

    当然,这只是我自己的看法,如果它是对的固然好,如果是错的,希望不要影响了其他人,也希望大家能用辩证的眼光来思考我的话。


0 0
原创粉丝点击