Working with the set of real numbers (was: Finding size of Variable)
Ian Kelly
ian.g.kelly at gmail.com
Tue Mar 4 06:19:59 EST 2014
On Mon, Mar 3, 2014 at 11:35 PM, Chris Angelico <rosuav at gmail.com> wrote:
> In constant space, that will produce the sum of two infinite sequences
> of digits. (And it's constant time, too, except when it gets a stream
> of nines. Adding three thirds together will produce an infinite loop
> as it waits to see if there'll be anything that triggers an infinite
> cascade of carries.) Now, if there's a way to do that for square
> rooting a number, then the CF notation has a distinct benefit over the
> decimal expansion used here. As far as I know, there's no simple way,
> in constant space and/or time, to progressively yield more digits of a
> number's square root, working in decimal.
The code for that looks like this:
def cf_sqrt(n):
"""Yield the terms of the square root of n as a continued fraction."""
m = 0
d = 1
a = a0 = floor_sqrt(n)
while True:
yield a
next_m = d * a - m
next_d = (n - next_m * next_m) // d
if next_d == 0:
break
next_a = (a0 + next_m) // next_d
m, d, a = next_m, next_d, next_a
def floor_sqrt(n):
"""Return the integer part of the square root of n."""
n = int(n)
if n == 0: return 0
lower = 2 ** int(math.log(n, 2) // 2)
upper = lower * 2
while upper - lower > 1:
mid = (upper + lower) // 2
if n < mid * mid:
upper = mid
else:
lower = mid
return lower
The floor_sqrt function is merely doing a simple binary search and
could probably be optimized, but then it's only called once during
initialization anyway. The meat of the loop, as you can see, is just
a constant amount of integer arithmetic. If it were desired to halt
once the continued fraction starts to repeat, that would just be a
matter of checking whether the triple (m, d, a) has been seen already.
Going back to your example of adding generated digits though, I don't
know how to add two continued fractions together without evaluating
them.
More information about the Python-list
mailing list