我被要求使用Bisection方法找到方程的根,并且只有{3}}循环使用Python 3. This线程显示如何使用该方法,但没有说明数字的解释在for
。
举个例子,我有函数
f(x)= x 2 - 2 * x - 3
我希望找到它的负根,从区间[-4,1]开始。
我设法用range()
循环编写函数,但我不明白我应该使用哪个范围,或者如何提出它。
这是我的代码,解决了这个问题:
for
c = -1(找到负根),f(c)= 0确认程序有效,i = 52表示在52次“尝试”二分后,它找到了正确答案。
我在...
a = -4
b = 1
c = (a + b)/2
for i in range(1000):
if f(c) == 0:
break
if f(a) * f(c) < 0:
b = c
elif f(a) * f(c) > 0:
a = c
c = (a + b) / 2
return c, f(c), i
中放了一个非常大的数字以确保找到了根,但为什么它只需要52次迭代?
另外,如果我的间隔变为[-2,1],我需要53次尝试。 为什么会这样?
答案 0 :(得分:1)
每次迭代,您将搜索间隔减半。在每次迭代中,您检查f(c)(中点的功能值)是否为0,在计算机浮点表示的精度范围内。
如果你选择区间[-101,99],你只需要在1次迭代中得到解,就像你点击c = -1那样。只要程序足够接近评估结果为0.000000
的实际根,程序就会停止你开始的宽度范围是5.什么是5除以2,52倍?实现中浮点数的准确度是多少?我敢打赌你接近两个花车之间的最小差异。
如果你真的想看到这个,请在循环中添加一个简单的行,就在顶部:
print a, b, c, f(c)
这将显示找到根目录的进度。
打印语句是一种低技术,有效的跟踪程序的方法。
评论回复
好点:我还没有足够强硬地说出具体案例。
你完成了52次迭代,因为这是程序在正确值上“绊倒”所花费的数量。当你改变并在53次迭代中进行更小范围时...简单的方法是说你第一次有点幸运。正如我 指出的那样,如果你开始使用-1作为其中点的东西,例如[-101,99],那么你将只完成一个迭代,尽管有更大的间隔。
答案 1 :(得分:1)
如果您在循环中print([a, b])
,则可以看到范围演变:
[-4, 1]
[-1.5, 1]
[-1.5, -0.25]
[-1.5, -0.875]
[-1.1875, -0.875]
[-1.03125, -0.875]
...
...
...
[-1.0000000000000284, -0.9999999999999929]
[-1.0000000000000107, -0.9999999999999929]
[-1.0000000000000018, -0.9999999999999929]
[-1.0000000000000018, -0.9999999999999973]
[-1.0000000000000018, -0.9999999999999996]
[-1.0000000000000007, -0.9999999999999996]
计算出的平均值-1.0000000000000007和-0.9999999999999996正好为-1。为什么?因为你已经达到浮标代表的极限。以下是所涉及的确切值:
>>> '%.60f' % -1.0000000000000007
'-1.000000000000000666133814775093924254179000854492187500000000'
>>> '%.60f' % -0.9999999999999996
'-0.999999999999999555910790149937383830547332763671875000000000'
>>> '%.60f' % (-1.0000000000000007 + -0.9999999999999996)
'-2.000000000000000000000000000000000000000000000000000000000000'
>>> '%.60f' % ((-1.0000000000000007 + -0.9999999999999996) / 2)
'-1.000000000000000000000000000000000000000000000000000000000000'
浮点存储52 bits of fraction,意思是前导1位后的52位。意味着你失去了比你的价值约1/2 52 小的东西。经过52个步骤后,您的初始5号范围大约为5/2 52 。这是你的价值-1的1/2 52 。因此,在那里,由于不精确,你很有可能偶然发现-1。
可能需要两个或三个步骤,因为5/2 52 仍然比1/2 52 大一点。你那里很幸运。使用您的其他初始范围[-2, 1]
,您就不那么幸运了。在达到-1之前,你的范围会缩小到[-1.0000000000000002, -0.9999999999999999]
。
如果您从[-4000000, 1]
开始,那么您需要72个步骤。它的步骤多了20步,因为初始范围是一百万倍,大约是2 20 。
另一种情况:如果您使用函数x**2 - 1000000
和初始范围[999.3, 1000.3]
,则需要41步。为什么?最终值(即根)是1000,初始范围是1。那是1/1000,所以约1/2 10 。所以要达到1/2 52 ,你只需要大约42个二等分。