Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 2.7 - Continued Fraction Expansion - Understanding the error [duplicate]

Tags:

I've written this code to calculate the continued fraction expansion of a rational number N using the Euclidean algorithm:

from __future__ import division

def contFract(N):
    while True:
        yield N//1
        f = N - (N//1)
        if f == 0:
            break
        N = 1/f

If say N is 3.245 the function is never ending as apparently f never equals 0. The first 10 terms of the expansion are:

[3.0, 4.0, 12.0, 3.0, 1.0, 247777268231.0, 4.0, 1.0, 2.0, 1.0]

Which is clearly an error since the actual expansion is only:

[3;4,12,3,1] or [3;4,12,4]

What's causing the problem here? Is it some sort of rounding error?

like image 397
ggordon Avatar asked Jun 29 '16 10:06

ggordon


1 Answers

The issue is you're testing f == 0 (integer 0) which is almost never true for floats. So the loop goes on forever.

Instead, check for some precision of equivalent to 0 (which can be wrong sometimes):

>>> from __future__ import division
>>>
>>> def contFract(N):
...     while True:
...         yield N//1
...         f = N - (N//1)
...         if f < 0.0001:  # or whatever precision you consider close enough to 0
...             break
...         N = 1/f
...
>>>
>>> list(contFract(3.245))
[3.0, 4.0, 12.0, 3.0, 1.0]
>>>

And in case f can be negative, do either -0.0001 < f < 0.0001 or abs(f) < 0.0001. Which is also considered inaccurate, see the linked article.

And wrt my comment to use int(N) instead of N//1 because it's clearer - it is slightly less efficient:

>>> import timeit
>>> timeit.timeit('N = 2.245; N//1', number=10000000)
1.5497028078715456
>>> timeit.timeit('N = 2.245; int(N)', number=10000000)
1.7633858824068103
like image 163
aneroid Avatar answered Oct 12 '22 23:10

aneroid