Skip to content

Instantly share code, notes, and snippets.

@somacdivad
Created December 11, 2023 02:16
Show Gist options
  • Save somacdivad/86b8a5768756ea60bc6b5acace2ce7a7 to your computer and use it in GitHub Desktop.
Save somacdivad/86b8a5768756ea60bc6b5acace2ce7a7 to your computer and use it in GitHub Desktop.
Infinite periodic continued fractions
def periodic(L: list):
"""Return an infinite periodic continued fraction representation."""
# Create a copy of the list and append it to itself.
# This creates an "infinite" list of the form [a0, ..., an, [a0, ..., an, [a0, ..., an, ...]]]
# The list is not actually infinite, it only has length n+1! It has infinite depth and finite length 🤯
S = list(L)
S.append(S)
return S
# EXAMPLES:
# Periodic continued fraction representation of golden ratio
golden_ratio = periodic([1])
# Periodic continued fraction representation of sqrt(2)
sqrt2 = [1, periodic([2])]
def convergents(continued_fraction, h=(0, 1), k=(1, 0)):
"""Yield the convergents of a continued fraction."""
if isinstance(continued_fraction, list):
N = len(continued_fraction) - 1
for i in range(N):
a_i = continued_fraction[i]
h_i, k_i = h[0] + a_i*h[1], k[0] + a_i*k[1]
yield h_i, k_i
h, k = (h[1], h_i), (k[1], k_i)
yield from convergents(continued_fraction[N], h, k)
else:
a_n = continued_fraction
h_n, k_n = h[0] + a_n*h[1], k[0] + a_n*k[1]
yield h_n, k_n
# EXAMPLES:
# Import islice to slice the convergents iterator.
from itertools import islice
# Print the first 10 convergents of the golden ratio
print('First 10 convergents of the golden ratio:')
for i, (h, k) in enumerate(islice(convergents(golden_ratio), 10), start=1):
print(f"{i}: {h, k}, {h/k}")
# First 10 convergents of the golden ratio:
# 1: (1, 1), 1.0
# 2: (2, 1), 2.0
# 3: (3, 2), 1.5
# 4: (5, 3), 1.6666666666666667
# 5: (8, 5), 1.6
# 6: (13, 8), 1.625
# 7: (21, 13), 1.6153846153846154
# 8: (34, 21), 1.619047619047619
# 9: (55, 34), 1.6176470588235294
# 10: (89, 55), 1.6181818181818182
print()
# Print the first 10 convergents of sqrt(2)
print('First 10 convergents of sqrt(2):')
for i, (h, k) in enumerate(islice(convergents(sqrt2), 10), start=1):
print(f"{i}: {h, k}, {h/k}")
# First 10 convergents of sqrt(2):
# 1: (1, 1), 1.0
# 2: (3, 2), 1.5
# 3: (7, 5), 1.4
# 4: (17, 12), 1.4166666666666667
# 5: (41, 29), 1.4137931034482758
# 6: (99, 70), 1.4142857142857144
# 7: (239, 169), 1.4142011834319526
# 8: (577, 408), 1.4142156862745099
# 9: (1393, 985), 1.4142131979695431
# 10: (3363, 2378), 1.4142136248948696
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment