jaki jest skuteczny sposób na znalezienie powtarzającego się miejsca po przecinku

24

Próbuję znaleźć skuteczny algorytm w Javie, aby znaleźć powtarzającą się część dziesiętną dwóch liczb całkowitych ai bgdzie a/b.

na przykład. 5/7 = 0,714258 714258 ....

Obecnie znam tylko metodę długiego podziału.

Jun Hao
źródło
2
Masz więc a = 5 ib = 7 i możesz łatwo obliczyć a / b w zmiennoprzecinkowym, ale chcesz wiedzieć, że powtarza się po 6 miejscach po przecinku?
Sparr

Odpowiedzi:

10

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/njest okresowa i ma okres lambda(n)niezależny m, który ma co najwyżej n-1 cyfry. Jeśli njest stosunkowo prime do 10, następnie okres lambda(n)od m/njest dzielnikiem phi(n)i ma co najwyżej phi(n)cyfr, gdzie phijest funkcja totient. Okazuje się, że lambda(n)jest to multiplikatywna kolejność 10 (mod n) (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.

Daniel B.
źródło
8

Pozwól n < d, a ty próbujesz wymyślić powtarzającą się część n/d. Niech pbę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ć pod 1 do nieskończoności i zatrzymać, gdy tylko dró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/dbędzie miał skończoną reprezentację dziesiętną tylko wtedy, gdy wszystkie czynniki pierwsze, dktóre nie są 2 lub 5, są również obecne n.

valtron
źródło
1
Ta odpowiedź wydaje się poprawna. Metoda opiera się na następującej „regule”: 0.123123... = 123/999 0.714258714258... = 714258/999999 (=5/7)itd.
PRZYJEDŹ Z
4
Nie udaje się w przypadkach takich jak 1/6 lub 5/12: \
razpeitia 11.11.13
1
@razpeitia Zrobiłem coś podobnego, ale działam we wszystkich przypadkach (w tym dzielenie liczb całkowitych). Sprawdź: codepad.org/hKboFPd2
Tigran Saluev
Zrobiłem implementację javascript podobną do @ TigranSaluev's na github.com/Macil/cycle-division
Macil
2

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.

Robert Harvey
źródło
4
„Przekształć go w ciąg” może wymagać dowolnych obliczeń precyzji i bardzo długiego ciągu, aby obliczyć dwie kopie powtarzającej się części łańcucha (a skąd wiesz, kiedy przestać obliczać? ​​.121212312121231212123 ... byłby problem)
Sparr
@Sparr Długość powtórzenia jest zawsze mniejsza niż mianownik.
@MichaelT Nie wiedziałem o tym. Jeśli to prawda, precyzja nie jest dokładnie „arbitralna”, ale może być dowolnie wysoka w zależności od mianownika.
Sparr
Nie sądzę, aby algorytm, do którego prowadzi łącze, działałby bez modyfikacji. Zawiera powtórzenia, które się nakładają, i przeszukuje cały ciąg (nie tylko kolejne dopasowania). Np. Najdłuższym powtarzanym substratem w „bananie” jest „ana”.
Web_Designer