Próbuję znaleźć skuteczny algorytm w Javie, aby znaleźć powtarzającą się część dziesiętną dwóch liczb całkowitych a
i b
gdzie a/b
.
na przykład. 5/7 = 0,714258 714258 ....
Obecnie znam tylko metodę długiego podziału.
Próbuję znaleźć skuteczny algorytm w Javie, aby znaleźć powtarzającą się część dziesiętną dwóch liczb całkowitych a
i b
gdzie a/b
.
na przykład. 5/7 = 0,714258 714258 ....
Obecnie znam tylko metodę długiego podziału.
Odpowiedzi:
Uważam, że istnieją tutaj dwa ogólne podejścia, możesz zasadniczo „brutalną siłą” szukać najdłuższego powtarzającego się łańcucha lub możesz rozwiązać go jako problem teorii liczb.
Dawno nie natknąłem się na ten problem, ale szczególny przypadek (1 / n) to problem nr 26 w Project Euler, więc możesz znaleźć więcej informacji, szukając skutecznych rozwiązań dla tej konkretnej nazwy. Jedno wyszukiwanie prowadzi nas do strony Eli Bendersky'ego, gdzie wyjaśnia swoje rozwiązanie . Oto niektóre teorie ze strony dziesiętnych rozszerzeń Mathworld :
Każda nieregularna część
m/n
jest okresowa i ma okreslambda(n)
niezależnym
, który ma co najwyżejn-1
cyfry. Jeślin
jest stosunkowo prime do 10, następnie okreslambda(n)
odm/n
jest dzielnikiemphi(n)
i ma co najwyżejphi(n)
cyfr, gdziephi
jest funkcja totient. Okazuje się, żelambda(n)
jest to multiplikatywna kolejność 10 (modn
) (Glaisher 1878, Lehmer 1941). Liczbę cyfr w powtarzalnej części rozwinięcia dziesiętnego liczby wymiernej można również znaleźć bezpośrednio z multiplikatywnej kolejności jej mianownika.
Moja teoria liczb jest w tej chwili trochę zardzewiała, więc najlepsze, co mogę zrobić, to skierować cię w tym kierunku.
Pozwól n < d
, a ty próbujesz wymyślić powtarzającą się część n/d
. Niech p
będzie liczbą cyfr w powtarzającej się części: wtedy n/d = R * 10^(-p) + R * 10^(-2p) + ... = R * ((10^-p)^1 + (10^-p)^2 + ...)
. Część w nawiasach jest serią geometryczną równą 1/(10^p - 1)
.
Tak n / d = R / (10^p - 1)
. Zmień kolejność, aby uzyskać R = n * (10^p - 1) / d
. Aby znaleźć R, zapętlić p
od 1 do nieskończoności i zatrzymać, gdy tylko d
równomiernie się dzieli n * (10^p - 1)
.
Oto implementacja w Pythonie:
def f(n, d):
x = n * 9
z = x
k = 1
while z % d:
z = z * 10 + x
k += 1
return k, z / d
( k
śledzi długość powtarzającej się sekwencji, dzięki czemu można na przykład odróżnić od 1/9 do 1/99)
Zauważ, że ta implementacja (jak na ironię) zapętla się na zawsze, jeśli rozwinięcie dziesiętne jest skończone, ale kończy się, jeśli jest nieskończone! Możesz jednak sprawdzić ten przypadek, ponieważ n/d
będzie miał skończoną reprezentację dziesiętną tylko wtedy, gdy wszystkie czynniki pierwsze, d
które nie są 2 lub 5, są również obecne n
.
0.123123... = 123/999
0.714258714258... = 714258/999999 (=5/7)
itd.
Dzielenie liczb wielocyfrowych? : /
Zamień wynik w ciąg, a następnie zastosuj do niego ten algorytm . Użyj BigDecimal, jeśli ciąg nie jest wystarczająco długi dla zwykłych typów.