Страницы

Поиск по вопросам

вторник, 31 декабря 2019 г.

Период десятичной дроби

#python #алгоритм #оптимизация


Задача : на вход в функцию подается два целых числа (int(a), int(b)). Вернуть нужно
частное a/b , причем повторяющиеся числа (период) нужно взять в скобки.

Примеры:

1/3  = >   0.(3)
29/12 = >  2.41(6)
5/3  = >  1.(6)


Подошел к решению задачи методом брутфорса. Перебирал дробную часть , искал совпадения.
Но в случае 1/117 в период входит более 90 чисел и перебор чисел занимает больше времени,
чем позволено в задаче.

Как по-другому решить эту задачу? Может есть более элегантное решение?
    


Ответы

Ответ 1



Для поиска периода рационального числа существует отдельный алгоритм. Перебираем одну за другой степени числа 10: 10, 100, 1000, 10000 и т.д. Смотрим на остаток от деления этого числа на знаменатель. Если остаток от деления равняется 1, значит степень числа 10, это длина периода. Например, если в знаменателе стоит 13, то: 10 % 13 = 10 100 % 13 = 9 1000 % 13 = 12 10000 % 13 = 3 100000 % 13 = 4 1000000 % 13 = 1 Получается, период равен 6. Этот период не зависит от того, что стоит в числителе (если дробь сокращена). Метод не работает, если знаменатель делится на 5 или 2. В таком случае его нужно делить на 2, или 5, пока получится число, которое не делится на 2, 5. В общем случае (как для вашего примера 1/117), придется использовать длинную арифметику. Алгоритм ищет только длину периода, что бы получить сам период, нужно делить самому.

Ответ 2



Я реализовывал в свое время деление в столбик и как только получал ту же пару делимое-делитель что уже была - считал что нашел период.

Ответ 3



Решение через деление в столбик . Огромное спасибо всем отписавшимся :) def convert(numerator, denominator): ans= str(numerator//denominator)+ "." l={} index=0 numerator = numerator%denominator l[numerator]=index t=False while t==False: if numerator==0: break digit = numerator*10//denominator numerator=numerator*10-(numerator*10//denominator)*denominator if numerator not in l: ans+=str(digit) index+=1 l[numerator]=index t=False else: ans+=str(digit)+")" ans=ans[:l.get(numerator)+len(ans[:ans.index(".")+1])]+"("+ ans[l.get(numerator)+len(ans[:ans.index(".")+1]):] t=True return ans

Комментариев нет:

Отправить комментарий