Ich versuche, einen effizienten Algorithmus in Java zu finden, um den sich wiederholenden Dezimalteil von zwei Ganzzahlen zu finden aund bwo a/b.
z.B. 5/7 = 0,714258 714258 ....
Ich kenne derzeit nur die Methode der langen Teilung.
Ich versuche, einen effizienten Algorithmus in Java zu finden, um den sich wiederholenden Dezimalteil von zwei Ganzzahlen zu finden aund bwo a/b.
z.B. 5/7 = 0,714258 714258 ....
Ich kenne derzeit nur die Methode der langen Teilung.
Antworten:
Ich glaube, dass es hier zwei allgemeine Ansätze gibt, Sie können im Wesentlichen "Brute Force" nach der längsten sich wiederholenden Zeichenfolge suchen oder Sie können es als ein Problem der Zahlentheorie lösen.
Es ist lange her, dass ich auf dieses Problem gestoßen bin, aber ein Sonderfall (1 / n) ist Problem Nr. 26 in Project Euler, sodass Sie möglicherweise mehr Informationen finden, indem Sie nach effizienten Lösungen für diesen bestimmten Namen suchen. Eine Suche führt uns zu Eli Benderskys Website, auf der er seine Lösung erklärt . Hier ist ein Teil der Theorie von Mathworlds Decimal Expansions-Seite :
Jeder unregelmäßige Bruch
m/nist periodisch und hat einen von ihmlambda(n)unabhängigen Zeitraumm, der höchstensn-1Ziffern lang ist. Wennnes sich um eine Primzahl von 10 handelt, ist die Periodelambda(n)vonm/nein Teiler vonphi(n)und hat höchstensphi(n)Ziffern, wobeiphies sich um die Totientenfunktion handelt. Es stellt sich heraus, dass dieslambda(n)die multiplikative Ordnung von 10 (modn) ist (Glaisher 1878, Lehmer 1941). Die Anzahl der Stellen im Wiederholungsteil der Dezimalerweiterung einer rationalen Zahl kann auch direkt aus der multiplikativen Reihenfolge ihres Nenners ermittelt werden.
Meine Zahlentheorie ist im Moment ein bisschen verrostet, also ist das Beste, was ich tun kann, Sie in diese Richtung zu lenken.
Lassen Sie n < d, und Sie versuchen, den sich wiederholenden Teil von herauszufinden n/d. Sei pdie Anzahl der Ziffern im Wiederholungsteil: dann n/d = R * 10^(-p) + R * 10^(-2p) + ... = R * ((10^-p)^1 + (10^-p)^2 + ...). Das Klammerteil ist eine geometrische Reihe, gleich 1/(10^p - 1).
Also n / d = R / (10^p - 1). Neu anordnen, um zu bekommen R = n * (10^p - 1) / d. Um R zu finden, gehen Sie pvon 1 bis unendlich und halten Sie an, sobald Sie sich dgleichmäßig geteilt haben n * (10^p - 1).
Hier ist eine Implementierung in Python:
def f(n, d):
x = n * 9
z = x
k = 1
while z % d:
z = z * 10 + x
k += 1
return k, z / d
( kVerfolgt die Länge der Wiederholungssequenz, sodass Sie beispielsweise zwischen 1/9 und 1/99 unterscheiden können.)
Beachten Sie, dass diese Implementierung (ironischerweise) eine Endlosschleife ausführt, wenn die Dezimalerweiterung endlich ist, aber endet, wenn sie unendlich ist! Sie können diesen Fall jedoch überprüfen, da n/dnur dann eine endliche Dezimaldarstellung dvorliegt, wenn alle Primfaktoren , die nicht 2 oder 5 sind, auch in vorhanden sind n.
0.123123... = 123/999 0.714258714258... = 714258/999999 (=5/7)usw.
Lange Trennung? : /
Verwandeln Sie das Ergebnis in eine Zeichenfolge und wenden Sie diesen Algorithmus darauf an. Verwenden Sie BigDecimal, wenn Ihre Zeichenfolge bei normalen Typen nicht lang genug ist.