що є ефективним способом пошуку десяткових повторень


24

Я намагаюся знайти ефективний алгоритм на Java, щоб знайти повторювану десяткову частину двох цілих чисел aі bде a/b.

напр. 5/7 = 0,714258 714258 ....

В даний час я знаю лише метод довгого поділу.


2
Отже, у вас є a = 5 і b = 7, і ви можете обчислити a / b у плаваючій точці досить легко, але що ви хочете знати, це повторення після 6 знаків після коми?
Спарр

Відповіді:


10

Я вважаю, що тут є два загальні підходи, ви, по суті, можете "грубою силою" шукати найдовший ряд, що повторюється, або ви можете вирішити це як проблему теорії чисел.

З давніх часів я зіткнувся з цією проблемою, але окремий випадок (1 / n) - це проблема № 26 проекту Project Euler, тому ви, можливо, зможете знайти більше інформації, шукаючи ефективні рішення для цього конкретного імені. Один пошук веде нас на веб-сайт Елі Бендерського, де він пояснює своє рішення . Ось деякі теорії зі сторінки Десятичні розширення Mathworld :

Будь-яка нерегулярна частка m/nє періодичною і має період, lambda(n)незалежний від m, який є не більшістю n-1 цифр. Якщо nвідносно просте 10, то період lambda(n)" m/nє дільником" phi(n)і має максимум phi(n)цифр, де phiє коефіцієнт підсилення. Виявляється, lambda(n)це мультиплікативний порядок 10 (мод n) (Glaisher 1878, Lehmer 1941). Кількість цифр у повторюваній частині десяткового розширення раціонального числа також можна знайти безпосередньо з мультиплікативного порядку його знаменника.

Моя теорія чисел на даний момент трохи іржава, тому найкраще, що я можу зробити, - це вказати вам у цьому напрямку.


8

Нехай n < d, і ви намагаєтесь з'ясувати повторювану частину n/d. Нехай pбуде кількість цифр у повторюваній частині: тоді n/d = R * 10^(-p) + R * 10^(-2p) + ... = R * ((10^-p)^1 + (10^-p)^2 + ...). Закріплена частина - це геометричний ряд, рівний 1/(10^p - 1).

Отже n / d = R / (10^p - 1). Переставити для отримання R = n * (10^p - 1) / d. Щоб знайти R, переведіть цикл pвід 1 до нескінченності та зупиніться, як тільки dрівномірно розділиться n * (10^p - 1).

Ось реалізація в 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

( kвідслідковує довжину повторюваної послідовності, тому ви можете розрізняти, наприклад, 1/9 та 1/99)

Зауважте, що ця реалізація (за іронією долі) циклічно назавжди, якщо десяткове розширення кінцеве, але припиняється, якщо вона нескінченна! Ви можете перевірити цей випадок, оскільки n/dвін матиме кінцеве десяткове представлення лише у тому випадку, якщо всі найпростіші коефіцієнти d, які не є 2 або 5, також є у n.


1
Ця відповідь здається правильною. Метод заснований на наступному "правилі": 0.123123... = 123/999 0.714258714258... = 714258/999999 (=5/7)і т. Д.
ПРИЙДІТЬСЯ

4
Це не вдається випадки, як 1/6 або 5/12: \
razpeitia

1
@razpeitia Я зробив щось подібне, але працюю у всіх випадках (включаючи ціле ділення). Ознайомтесь: codepad.org/hKboFPd2
Тигран Салуєв

Я зробив реалізацію javascript, схожу на @ TigranSaluev's, на github.com/Macil/cycle-division
Macil

2

Довгий поділ? : /

Перетворіть результат у рядок, а потім застосуйте до нього цей алгоритм . Використовуйте BigDecimal, якщо ваш рядок недостатньо довгий із звичайними типами.


4
"Перетворити його в рядок" може зажадати довільних точних обчислень та дуже довгого рядка, щоб обчислити дві копії повторюваної частини рядка (а як ви знаєте, коли припинити обчислення? .1212123121212121212123 ... було б проблемою)
Спарр

@Sparr Довжина повторення завжди менша за знаменник.

@MichaelT Я про це не знав. Якщо правда, точність не є точно "довільною", але може бути довільно високою залежно від знаменника.
Спарр

@Sparr math.stackexchange.com/questions/298844 / ... хоча я знаходжу everything2.com/title/recurring+decimal більш читабельним.

Я не думаю, що алгоритм, на який ви посилаєтесь, працював би без змін. Він включає повторення, які перекриваються, і він здійснює пошук по всій рядку (не тільки для послідовних збігів). Наприклад, найдовша повторювана підрядок у "банані" - "ана".
Web_Designer
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.