Python 和逐次逼近法

学习如何使用这个示例脚本在 Python 中进行逐次逼近。
398 位读者喜欢这个。
Best of Opensource.com: Programming

Zagrev on Flickr. CC BY-SA 2.0

我在院子里做一些工作,我想知道能套住 4x6 英寸柱子的最小圆圈。当然,就像 2x4 不是 2 英寸乘 4 英寸一样,4x6 柱子(他们称之为“标称”尺寸)实际上是 3.5 英寸乘 5.5 英寸,所以这个最小圆圈的直径是 3.5x5.5 英寸矩形的对角线。毕达哥拉斯定理告诉我们,这将是 3.5 的平方和 5.5 的平方之和的平方根。当时,我只有手机,它的计算器只有基本的数学运算,那么如何得到 42.5 的平方根呢?逐次逼近法。

你做出初步猜测,知道它大于 6 但小于 7,并尝试 6.2,也许是 6.3,等等。数字 6.5 非常接近,平方为 42.25,所以你继续到下一个小数点后一位。最后,你达到 6.5192,并认为已经足够接近了。你不需要计算器上的平方根函数来做这个。

不久前,我突然想到,用手“计算”平方根的方法只不过是在纸上使用相同的方法,所以我认为教 Python 如何做到这一点会很有趣。在进一步深入之前,我想补充一点,我完全意识到 Python math 模块有一个 sqrt 函数可以做到这一点,但这远不如创建我自己的脚本有趣。

我的方法是让脚本询问想要计算平方根的值,然后询问小数点位数,然后逐步逼近平方根,这将涉及大量的重复、测试和重新测试。我想要的是某种递增循环,并进行测试以查看我是低于还是高于期望值。这是最终结果

#!/usr/bin/env python
# sqrt.py - find square root

def sqtest(num, orig, ind):
    sq = 0
    while sq <= orig:
        num = num + ind
        sq = num * num
    num = num - ind
    return num

n = float(0) # this is our working number. We start at zero and increment.

innum = input("For what number would you like to get the square root? ")
i = input("To how many decimal places? ")

inc = float(10)
i += 1
if (innum < 0):
    i = 0
while i:
    inc = inc * 0.1
    n  = sqtest (n, innum, inc)
    i -= 1
if (innum >= 0):
    sq = n * n
    print "Approximate square root of " + str(innum)+ " is " + str(n) + "\n(Actual square of this would be "+str(sq)+")"
else:
    print "This would be an imaginary number"

现在,跳过缩进部分,称为函数,它以 def sqtest 开头。你要告诉 Python 从零开始探索,因为你可能在某个时候想要计算 0 到 1 之间数字的平方根。在此之后,你询问你需要平方根的数字,然后询问你想要多少位小数精度。

虽然看起来你的初始增量将是 10,但这将被重构,以便你稍后可以顺利地处理小数。将小数位数加 1,因为在处理小数之前,你将有一个用于个位及以上的循环。接下来,你检查输入的数字是否小于零,这样你就不会在虚数上浪费时间。

现在进入循环,你将你的工作数字 n、你的原始数字 innum 和当前增量(最初是 10 x 0.1)发送到 sqtest 函数。

sqtest 中,你将当前工作数字的值、你需要计算平方根的数字和当前增量值发送到该函数。在清除任何先前的值之后,你检查工作数字加上新增量的平方,如果它小于 innum,则递增,直到平方大于 innum,此时你后退一个增量刻度,并将新的工作数字发送回去。较低的 while 循环现在采用你的最后一个增量值并取其十分之一,然后你再次开始 sqtest。你重复此操作,直到完成请求的小数位数。

这是一个示例输出

For what number would you like to get the square root? 28837465
To how many decimal places? 6
Approximate square root of 28837465 is 5370.052606
(Actual square of this would be 28837464.9912)

请注意,我不仅显示了平方根,还显示了它的实际平方,以便更好地了解我有多接近。要记住的一件事是最后一位数字的不确定性。由于此脚本的工作方式,此值在小数点后 6 位被截断,而不是四舍五入,因此你不知道第七位小数是大于还是小于 5。最好拥有比你认为需要的更多位数,以便你可能决定进行的任何四舍五入都是准确的。

你可能会认为从 0 开始并以 1 递增对于大数字来说会很耗时,但我认为你会惊讶于解释器在这里运行的速度有多快——这个 8 位数字的平方根,精确到小数点后 6 位,几乎是瞬间完成的。对于真实世界的数字,这已经足够了,即使对于 15 位数字加上小数点后 6 位,也可能只需要 3 秒。但是,在某些时候,可能会出现有效位数的问题。

标签
Greg Pittman
Greg 是一位肯塔基州路易斯维尔的退休神经科医生,长期以来对计算机和编程感兴趣,从 1960 年代的 Fortran IV 开始。当 Linux 和开源软件出现时,它激发了他学习更多东西并最终做出贡献的决心。他是 Scribus 团队的成员。

7 条评论

这里有一些家庭作业。只需稍作修改,你就可以将其变成立方根查找器。
这是新的输出

你想要计算哪个数字的立方根? 384857
精确到多少位小数? 6
384857 的近似立方根是 72.738855
(这个数的实际立方是 384856.992155)

这被称为二分法。

二分法听起来像是将某物切成两半,但实际上它是逐次逼近法。

回复 ,评论者 Zahir Jacobs (未验证)

作为一名神经科医生,我的想法之一是另一种真实世界的逐次逼近法是投手练习投球。这就是为什么,如果你有技能(代码?),你会通过练习变得越来越好。

我使用一个名为 dec2dyadic 的 ksh (Korn shell) 脚本做类似的事情。它使用类似的迭代将十进制实数转换为整数加上二进分数(即,分母是 2 的幂)。这对于能够将实数 (20.777) 转换为标准尺或码尺上的东西 (20 25/32) 很有用。或者,你可以让它取某个数字(长度),并类似地将其分成整数个二进部分(例如将木板切割成 5 个相等的长度)。你可以指定边距或灵敏度。这是在我开始学习 python 之前。 ;-) 你可以在这里找到副本:ftp://ftp.cs.duke.edu/pub/des/scripts/dec2dyadic

我目前正在学习 Python,并且很喜欢这篇文章。我已经进行了调整,使其可以在 Python3 中工作

#!/usr/bin/env python
# sqrt.py - 查找平方根

def sqtest(num, orig, ind)
sq = 0
while sq <= orig
num = num + ind
sq = num * num
num = num - ind
return num

n = float(0) # 这是我们的工作数字。我们从零开始递增。

innum = eval(input("你想要计算哪个数字的平方根? "))
i = eval(input("精确到多少位小数? "))
inc = float(10)
i += 1
if (innum < 0)
i = 0
while i
inc = inc * 0.1
n = sqtest (n, innum, inc)
i -= 1
if (innum >= 0)
sq = n * n
print ("" + str(innum)+ " 的近似平方根是 " + str(n) + "\n(这个数的实际平方是 "+str(sq)+")")
else
print ("这将是一个虚数")

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 获得许可。
© . All rights reserved.