Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 了解使用二分法寻找解决方案的迭代次数_Python_Algorithm_Python 3.x_For Loop_Bisection - Fatal编程技术网

Python 了解使用二分法寻找解决方案的迭代次数

Python 了解使用二分法寻找解决方案的迭代次数,python,algorithm,python-3.x,for-loop,bisection,Python,Algorithm,Python 3.x,For Loop,Bisection,我被要求使用二分法找到一个方程的根,对于Python 3中的循环,我只需要。thread显示了如何使用该方法,但没有说明range()中的数字 作为一个例子,我有这个函数 f(x)=x2-2*x-3 我想找到它的负根,从区间[-4,1]开始 我设法用一个for循环来编写函数,但我不知道应该使用哪个范围,或者如何使用它 以下是解决问题的代码: ... a = -4 b = 1 c = (a + b)/2 for i in range(1000): if f(c) == 0:

我被要求使用二分法找到一个方程的根,对于Python 3中的循环,我只需要
。thread显示了如何使用该方法,但没有说明
range()
中的数字

作为一个例子,我有这个函数

f(x)=x2-2*x-3

我想找到它的负根,从区间[-4,1]开始

我设法用一个
for
循环来编写函数,但我不知道应该使用哪个范围,或者如何使用它

以下是解决问题的代码:

...
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
。。。
a=-4
b=1
c=(a+b)/2
对于范围(1000)内的i:
如果f(c)==0:
打破
如果f(a)*f(c)<0:
b=c
elif(a)*f(c)>0:
a=c
c=(a+b)/2
返回c,f(c),i
c=-1(找到负根),f(c)=0确认程序工作,i=52表示在52次对分“尝试”后,它找到了正确答案

我在
range()
中输入了一个非常大的数字,以确保找到了根,但为什么它只需要52次迭代


另外,如果我的间隔改为[-2,1],我需要53次尝试为什么会这样?

每次迭代都会将搜索间隔缩短一半。在每次迭代中,检查中点处的函数值f(c)是否在计算机浮点表示的精度范围内为0

如果你选择区间[-101,99],你只需要一次迭代就可以得到解,当你点击c=-1的时候。只要程序足够接近实际根,并且计算值达到0.000000,程序就会停止

您从宽度为5的范围开始。5除以2,52是多少?在您的实现中,浮点数的精度是多少?我敢打赌,你已经接近两个浮点数之间的最小差值了

如果您真的想看到这一点,请在循环的顶部添加一条简单的线:

print a, b, c, f(c)
这将向您显示查找根的进度

打印语句是跟踪程序的一种低技术、有效的方法

评论回复

很好的一点是:我还没有把具体的情况说得够清楚

您完成了52次迭代,因为这是程序“偶然”发现正确值所花费的时间。当你改变并在53次迭代中以较小的范围完成它时。。。最简单的方法就是说你第一次有点幸运。正如我所指出的,如果你从以-1为中点的东西开始,比如[-101,99],那么你将只在一次迭代中完成,尽管间隔要大得多。

如果你在循环中打印([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.9999999996的平均值正好是-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'
浮动存储,表示在前导1位之后52位。这意味着你失去的东西比你价值的1/252小。经过52步后,您最初的尺码范围已变为5/252左右。这大约是你价值的1/252-1。所以在那个里,你们有一个很好的机会,因为不精确,恰好碰到-1

它可能需要两到三个步骤,因为5/252仍然比1/252大一点。你很幸运。用你的另一个初始范围
[-2,1]
你就没那么幸运了。在那里,在到达-1之前,您的范围将缩小到
[-1.0000000000000002,-0.99999999999999]

如果您从
[-4000000,1]
开始,则需要72个步骤。因为初始范围是100万倍大,大约是220,所以要多走20步


另一种情况:如果使用函数
x**2-1000000
和初始范围
[999.3,1000.3]
,则需要41个步骤。为什么?最终值(即根)为1000,初始范围大小为1。这是1/1000,所以大约是1/210。因此,要达到1/252,你只需要大约42个二等分。

你至少读过二等分方法背后的理论吗,或者换句话说,你知道你的代码发生了什么吗?嗯,你链接到的页面上的公认答案确实使用了for循环,不是吗?投票结束这个问题的人根本不理解这个主题。他/她问的问题很清楚。顺便说一句,一般来说,你不应该检查这个条件
f(c)==0
,而应该检查
f(c)
是否足够接近零,即类似于
f(c)<1e-09
。这是因为当使用浮点数时,会出现“舍入”错误,即使用浮点数进行计算时会失去精度,因为计算机的有限性…@nbro你完全正确,通常我使用math.isclose()来实现这一点,但在这种情况下,我被迫避免使用更复杂的函数。我试着按照你的建议去做(第一个条件f(c)<0.000000001),但是我得到了c=-0.25,这让我更加困惑!这并不能真正解释它的特殊情况,但它只是对该方法的一般性解释,而不是OP所要求的。谢谢,我确实注意到,对于以零为中点的区间,我只需要1次迭代(第一个条件第一次为真)。虽然我从表面上理解了这个方法,以及为什么它最终会起作用,但我仍然不明白为什么在这个例子中52是答案,或者在我提到的另一个时间间隔中53是答案。我猜这与Python上浮点运算的有限精度有关,但准确程度如何?这是一个纯对分何时足够接近实际根的问题,您可以在选择的答案中看到。这正是我想要理解的!!在看到您的答案后,我重新阅读了Python教程(15),并对其进行了分析