尝试通过二等分查找来查找非完美多维数据集的多维数据集根时出现无限循环

时间:2019-03-23 15:46:42

标签: python python-3.x bisection

此代码在deltanum = 0.0000000000001时给出非常准确的结果,但是在deltanum = 0.00000000000001时进入无限循环(向deltanum添加另一个零)。

它仅在非完美的多维数据集上出现,对于1000这样的完美多维数据集也可以正常工作。为什么?

我是OSSU之后的编程新手。

num = 100
high = num
low = 0
icount = 0
cuberoot = (high + low)/2      #cuberoot of num
deltanum = 0.00000000000001
while abs(cuberoot**3 - num)>=deltanum:
    icount+=1
    print(icount)
    if cuberoot**3 > num:
        high = cuberoot
    elif cuberoot**3 < num:
        low = cuberoot
    else:
        break
    cuberoot = (high + low)/2
print("Cube root: " + str(cuberoot))
print("Number of iterations: " + str(icount))

2 个答案:

答案 0 :(得分:2)

您正在使用<canvas id="c"></canvas> <script src="https://threejsfundamentals.org/threejs/resources/threejs/r102/three.min.js"></script> <script src="https://threejsfundamentals.org/threejs/resources/threejs/r102/js/controls/OrbitControls.js"></script> s。 float数学在精确度方面是有缺陷的-您的增量可能太小而无法正常工作,并且您的解决方案会在数值之间翻转而从未达到您的float条件限制。有关为什么有时会“中断”浮动的更多原因,请参见Is floating point math broken?

您也可以将其限制为一定的重复次数:

while

输出:

num = 100
high = num
low = 0
icount = 0
maxcount = 100000
cuberoot = (high + low)/2      #cuberoot of num
deltanum = 0.00000000000001
while abs(cuberoot**3 - num)>=deltanum:
    icount+=1
    print(icount)
    if cuberoot**3 > num:
        high = cuberoot
    elif cuberoot**3 < num:
        low = cuberoot
    else:
        break
    cuberoot = (high + low)/2

    if icount > maxcount:
        print("Unstable solution reached after ",maxcount, "tries")
        break
print("Cube root: " + str(cuberoot) + " yields " + str(cuberoot**3))
print("Number of iterations: " + str(icount))

答案 1 :(得分:0)

大多数人会用epsilon来命名,并将delta用在cuberoot**3 - num上。

最后,您希望这个表达式,

    cuberoot = (high + low)/2

在每次迭代中,您的答案将为您带来大约一点点的精度。 (在开头附近,每次大约将错误位的数量减少一半。)

您在抱怨IEEE-754 double在计算多维数据集时精度有限,并且差异也很大。 53位几乎为16位十进制数字,您的epsilon为1e-14。 但是,您发现,输入num长几位数会吃掉您的空白。

对于更高精度的计算,您可能更喜欢使用Decimal。 或者,查看gmp库。

您相信某个循环不变式成立, cuberootcuberoot ** 3的数量将在每次迭代中改变。 验证很简单。 只需将它们分配给临时变量,并验证它们是否已更改。 如果没有,请尽早终止循环。 更一般而言,要检测少数几个极限值之间的振荡,请将先前的值放入set中,并在看到重复值时尽早终止。