初等数学题解:求平方根

===》点我返回目录《===

数学里面有很多操作是互逆的,正向操作简单,但是逆向操作很复杂。平方的逆操作是开平方根,这个开方操作计算起来并不容易。费了我们先人很多功夫。

在中学的课本中,会讲到竖式计算法。它的基本思路是这样的:

比如1156是四位数,不难看出它的平方根是个两位数,且十位上的数字是3.于是问题就转换成:怎样求出它的个位数a?根据两数和的平方公式,可以得到

1156=(30+a)2=302+2*30a+a2,所以 1156-302=2×30a+a2,即 256=(30*2+a)a,

这就是说, a是这样一个数,它与30*2的和,再乘以它本身,等于256.

为便于求得a,可用下面的方法进行计算:

3是平方根的十位数.将1156-302,得到余数 256,把这个余数试除以30×2,得4(如果未除尽则取整数位).由于4与30×2的和64,与4的积正好等于256,开方正好开尽,4就是所求的个位数a.于是得到 1156=34^2。对于不能开尽的数,通过补充00来一步步接近。

这个最早出现在中国古代数学著作《九章算术》(约2000年前)的“少广”章。这是中国古代数学的杰出成就,它系统地介绍了中国古代的数学体系。但是该书的整个体系是偏向于实用的,没有原理证明,这与以《几何原本》为代表的公理逻辑体系形成鲜明对比,所以流于表面解决问题,后劲不足,最后没有发展出现代科学。这是我们在了解中国古代科技成就的时候需要明了的。

                                                 

            (《九章算术》)                                                                    (《几何原本》)

上面的开平方运算非常繁,我们现在很少用到。感谢古人的不辞辛劳,通过手工计算给了我们一个庞大的开方表。技术的进步都是一点一滴的,通过无数代人接力,历经千年万年,人类整体智慧就会到达一个令人惊叹的地步。所以,我们永远不要忘记先人的呕心沥血。

 

在计算机算法里,我们其实不是用的上述办法,那实在太麻烦了,我们会用几种别的方法,比如二分法,如牛顿逼近法(牛顿真的是大神,学着学着就会碰到他)。

二分法是一种渐渐逼近的办法,比如要求10的平方根,观察一下不难得知这个数肯定在0到10之间,我们取中间值5来算一下,为25,比10大,所以这个数一定比5小而比0大,我们再次取中间值2.5,这样一直算下去逐步逼近真数。

这个办法很笨很笨,通过很多次循环一点点接近。这里再次看到了计算机的笨和快,因为计算机跑得快,所以笨方法还很有效。

我们用下面程序实现上面的算法:

print ("Square root calculator")

x = 10

a=0

b=x

c=(a+b)/2

while c**2-x>0.0001 or c**2-x<-0.0001:

    if c**2>x:

        a=a

        b=c

    if c**2<x:

        a=c

        b=b

    c=(a+b)/2

print (c)

稍微解释一下,x为给定的原值,a为平方根的下限,b为平方根的上限,c为猜测的值,初始为中间值c=(a+b)/2,我们用这个值逼近真值。

While 的循环条件为精度要求。如果还没有达到精度要求,就判断试值的平方大于小时小于原值,如果大于,说明这个试值猜测得大了,那么下一个猜测得值应该在下限与当前试值中间,所以我么你重新划定上下限,这就是a=a,b=c 两句的含义,反之,我们用a=c,b=b划定上下限。这里用到了if语句,就是我们讲的层序结构中的decision分支结构。

之后再用新的上下限的中间值当成下一个试值。一直这么循环下去,最后得到符合精度要求的结果值。你最好拿起笔在纸上把这个过程跟踪一遍。

要记住一点,其实我们得不到真值的,得到的永远是近似值。

自然,我们审视上面的程序的时候,也会发现问题。有了以前的基础,估计你也能知道几个明显的问题,第一个就是x=10,这个写死了,不好,应该是从外部接受一个值。除了这个呢?还有没有问题?有的,你看到了,这个程序没有处理负数。

但是,这个程序最大的问题还不在这里,而是有一个大错误(程序员的术语是bug。1947年9月9日,Grace Hopper发现了第一个电脑上的bug:Mark II计算机不能正常工作。经过排查,发现是一只飞蛾意外飞入了电脑内部而引起的故障。Grace Hopper用镊子夹出了飞蛾,把错误解除,并在日记本中记录下了这一历史事件。)

 

(Grace Hopper工作日志。历史上第一个bug记录于此。 图片来自Wikipedia)

回到这个bug上来,如果给定的这个值小于1,这个程序会陷入无穷循环中,结束不了了。这是因为x<1的时候,x的平方根是大于x的,落在的0到x区间之外。所以我们要改进一下我们的算法,判断一下x,如果x<1,就把上下限设定为x到1之间。修改这个bug后的程序如下:

print ("Square root calculator")

x = float(input("enter one number:"))

if x>1:

    a=0

    b=x

elif x>=0:

    a=x

    b=1

else:

    print("error: negative number.")

    exit()

c=(a+b)/2

while c**2-x>0.0001 or c**2-x<-0.0001:

    if c**2>x:

        a=a

        b=c

    if c**2<x:

        a=c

        b=b

    c=(a+b)/2

print (c)

修改后的程序,原值由外部输入,判断了大于1大于0小于0三种情况。其中用到了exit()这个Python提供的系统函数,用于退出程序执行。这个办法不是很好,以后我们会讲到怎么更好地处理。

有些用心的人会想知道我们究竟用了多少次循环才得到了这个逼近的数,这里与精度与关,你可以在循环代码里面加上一个计数器,看看结果。

我自己试验的结果,四位精度下,计算10的平方根,循环18次,十位精度下是35次。

有一些人特别好奇,究竟多少位精度合适呢?我们计算圆周率Pi的时候经常也会有这样的疑惑。这个与对计算结果的要求有关了,反正呐,我看过一个说明,如果Pi取小数点后35位,那么计算出来的太阳系的周长的值的误差只有一个原子那么一点。

有时候会觉得数学真的很神奇,让我们坐在桌子前用一支铅笔居然能算出浩瀚的宇宙。

还有一些严谨的人在使用算法的时候老是心里犯嘀咕:怎么知道这个算法本身是正确的呢?一般的做法是多测试几个数。但是数是无穷的,测试再多也不能表明算法是正确的,算法需要证明才能成为真理。大家放心,这些算法都是得到了证明的。我这里不给出证明,这需要用到高等数学知识,你们可以从下面的表达感受一下:

求解 f(x)=x2−n 的零点,在 [0,n] 的区间上,f(x)=x2−n 自然单调递增,可证二分法必然收敛。

这已经到了初等数学知识的边界了(中国的数学到此为止)。我们需要下车,再换乘高等数学(近代的数学)的列车,也有一批人会永久下车。

在计算平方根的几种算法中,还有一种用得比较广泛,就是牛顿逼近法,这个算法更加高效。

它用到了迭代,公式为Xi+1=Xi - (Xi2 - n) / (2Xi) =(Xi + n/Xi) / 2。有了这个迭代公式,程序就好编写了:

n=float(input("enter one number:"))

if n>=0:

    y=n/2

    while y**2-n>0.000001 or y**2-n<-0.000001:

        y=(y+n/y)/2

    print(y)

else:

    print("Error: negative number")

解释一下,初始值取的是n/2,不是取的n,因为n的平方根不会超过n/2。并且这个方法不需要单独考虑小于1的情况,它自己通过迭代会收敛到真值。

程序的主体就是那个while循环实现迭代公式,y=(y+n/y)/2。

那么我们究竟用了多少次迭代呢?我自己试验的结果,计算10的平方根,十位精度下是5次。

看到牛顿逼近算法的力量了吧?程序更加简洁,效率更高。

这个算法其实是一个推论,先就有数学上的严格的表达和证明。它使用函数 f(x) 的泰勒级数的前面几项来寻找方程 f(x)=0 的根。该法效率高,证明它是平方收敛的,该法应用广,并不限于求解实数的平方根,相反求解实数的平方根只是其一个具体的应用而已。

对于求解实数平方根的函数 f(x)=x2−n, 自然其根的迭代公式为:

Xn+1 = Xn−f(Xn)/f′(Xn) = Xn−f(Xn)/2Xn

我们不深究理论,但是从这里我们可以感受到牛顿的伟大和近代数学的魅力,它帮助我们精确分析时空和运动。天不生牛顿,万古如长夜。

 

(Issac Newton,1643.1.4-1727.3.31,维基百科)

有一首诗写道:

自然的法则隐藏在幽暗之中,

上帝说:

让牛顿降生吧。

于是有了光明。

(英格兰诗人Alexander Pope亚历山大·蒲柏)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值