Jetzt fehlt nur noch die Ermittlung der Liste (bis zu einer bestimmten Schrittzahl) aus einer gegebenen Zahl:

# Annäherung einer reellen Zahl durch einen Kettenbruch
def listFromNumber(x, steps):
    l = []
    for i in range(steps):
        i = floor(x)       # ganzzahliger Anteil
        l.append(i)
        if abs(x-i) < 0.00000001:
            break
        x = 1 / (x-i)      # weiter mit Kehrwert des Rests
    return l
    
echteMondwochen = 29.53059 / 7
listFromNumber(echteMondwochen, 5)

Nun wenden wir diese Funktionen an, um uns die ersten Näherungsbrüche für unsere Monatszahl zu erzeugen:

print("Schritte | Näherungswert | Jahre bis 1 Tag Abweichung")
for i in fromTo(1,7):
    naeherung = rationalFromList(listFromNumber(echteMondwochen, i))
    relativeAbweichung = naeherung/echteMondwochen - 1
    tageAbweichungProJahr = relativeAbweichung * 365.24
    jahreBisTagAbweichung = abs(1/tageAbweichungProJahr)
    print("{0:8} | {1:13} | {2}".format(i, naeherung, jahreBisTagAbweichung))

Im sechsten Schritt haben wir unser Getriebe wieder bekommen. Wenn Sie dies z.B. mit dem fünften Schritt vergleichen, sehen Sie, dass sich die Genauigkeit von 9 auf 122 Jahre verbessert hat. Trotzdem wird das Getriebe nicht komplizierter, im Gegenteil: Für 97/23 bräuchten wir Zahnräder mit 97 und 23 Zähnen, weil beide Zahlen Primzahlen sind. Dagegen lässt sich 135/32 in zwei einfachere Übersetzungen zerlegen:

\def\green{\bbox[#d0ffd0,2pt]} \def\pink{\bbox[#ffe0e0,2pt]} \frac{135}{32} = \frac{3^3\cdot 5}{2^5} = \pink{\frac 9 4} \cdot \frac{15}8 = \green{\frac{18}8} \cdot \frac{15}8

Zahnräder mit vier Zähnen sind mechanisch unmöglich, so dass wir wieder zur unserer Lösung (18/8) · (15/8) kommen.

Die Klasse ContFrac

In mathGUIde gibt es die fertige Klasse ContFrac. Damit können wir die komplette Berechnung so durchführen:

echteMondwochen = 29.53059 / 7
print("Schritte | Näherungswert | Jahre bis 1 Tag Abweichung")
for i in fromTo(1,7):
    cf = ContFrac(echteMondwochen, i)
    naeherung = cf.toRational()
    relativeAbweichung = naeherung/echteMondwochen - 1
    tageAbweichungProJahr = relativeAbweichung * 365.24
    jahreBisTagAbweichung = abs(1/tageAbweichungProJahr)
    print("{0:8} | {1:13} | {2}".format(i, naeherung, jahreBisTagAbweichung))