Я пытаюсь найти эффективный алгоритм в 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это функция totient. Оказывается, чтоlambda(n)это мультипликативный порядок 10 (модn) (Glaisher 1878, Лехмер 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, если ваша строка недостаточно длинна для обычных типов.