Search code examples
pythonpython-3.xfloating-pointfloating-accuracy

Why is my program stopping when doing a seemingly infinite loop?


This must be really obvious but I am currently doing a little tutorial that features this code snippet:

n=0
a=1
while a>0:
    n=n+1
    a=(1.0+2.0**(-n))-1.0
    print (n)

And I've tried to run it but it keeps getting stuck at n=53. Why? I just assumed that while would always be true ...


Solution

  • If you change the last line to print(n, a) you can see what's happening more clearly:

    n = 0
    a = 1
    while a > 0:
        n = n + 1
        a = (1.0 + 2.0 ** (-n)) - 1.0
        print(n, a)
    

    Output:

    1 0.5
    2 0.25
    3 0.125
    4 0.0625
    # ...
    50 8.881784197001252e-16
    51 4.440892098500626e-16
    52 2.220446049250313e-16
    53 0.0
    

    As you can see, a is half the size each time through the loop. Eventually, 2.0 ** (-n) is so small that floating point math (which has limited precision) is unable to tell the difference between 1.0 and 1.0 + 2.0 ** (-n):

    >>> 1.0 + 2.0 ** -51
    1.0000000000000004
    >>> 1.0 + 2.0 ** -52
    1.0000000000000002
    >>> 1.0 + 2.0 ** -53
    1.0
    

    … and when that happens, subtracting 1.0 from 1.0 gives you 0.0, and the while loop terminates.