Я намагаюся знайти ефективний алгоритм на Java, щоб знайти повторювану десяткову частину двох цілих чисел aі bде a/b.
напр. 5/7 = 0,714258 714258 ....
В даний час я знаю лише метод довгого поділу.
Я намагаюся знайти ефективний алгоритм на Java, щоб знайти повторювану десяткову частину двох цілих чисел aі bде a/b.
напр. 5/7 = 0,714258 714258 ....
В даний час я знаю лише метод довгого поділу.
Відповіді:
Я вважаю, що тут є два загальні підходи, ви, по суті, можете "грубою силою" шукати найдовший ряд, що повторюється, або ви можете вирішити це як проблему теорії чисел.
З давніх часів я зіткнувся з цією проблемою, але окремий випадок (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). Кількість цифр у повторюваній частині десяткового розширення раціонального числа також можна знайти безпосередньо з мультиплікативного порядку його знаменника.
Моя теорія чисел на даний момент трохи іржава, тому найкраще, що я можу зробити, - це вказати вам у цьому напрямку.
Нехай 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.
0.123123... = 123/999 0.714258714258... = 714258/999999 (=5/7)і т. Д.
Довгий поділ? : /
Перетворіть результат у рядок, а потім застосуйте до нього цей алгоритм . Використовуйте BigDecimal, якщо ваш рядок недостатньо довгий із звичайними типами.