2015-04-03 3 views
1

Я пытаюсь поместить все десятичные разряды 1/n в список в Python.Десятичные разряды в Python

def dec(n): 

    result = float(1)/n 
    while (result >= 1): 
     result = result - 1 

    while (result != 0): 
     result = result * 10 
     decimals = int(result) 
     yield(decimals) 
     result = result - decimals 

Однако, когда я попытался list(dec(3)), он не дает мне список полный 3s, но вместо того, чтобы что-то вроде [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 7, 2]

Как мне это исправить?

+0

Знаете ли вы, что список Python не может продолжаться вечно? – user2357112

+1

Также обратите внимание, что точность с плавающей запятой - вещь. Поплавки в компьютере подобны пациентам - у вас слишком много операций над ними, и они умирают. (Ну, не совсем, но читайте http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). Если вы хотите сделать бесконечное деление точности, просто выполните алгоритм деления длинной руки самостоятельно, используя только целые числа. – Amadan

+0

@ user2357112 да, но даже так, я хотел бы, чтобы я мог получить все 3s, а не другие числа. Я думаю, мне нужен какой-то трюк, так как мой код не ошибается, но он не дает ожидаемого результата. – viethaihp291

ответ

3

Поскольку поплавки Python представлены в двоичных, поплавочные представления фракций не просто неточны - десятичное приближение часто так же неточно, но и неточно интригующим образом. Мы используем для аппроксимации фракции, такой как 1/3, как-то вроде 0,33333333333, или 33333333333/10 ** 10 (при условии, что 10 значащих цифр). Однако двоичная с плавающей запятой, используемая Python, представляет числа в виде дробей с знаменателем силы двух. В этом представлении 1/3 аппроксимируется как 6004799503160661/2 ** 54, а цифры в вашем выходе поступают из этой фракции.

Для расчета цифр в десятичной приближения дроби 1/3, импортировать decimal модуль и заменить float(1) с decimal.Decimal(1). Decimal type был разработан с явной целью поддержки того, что вы пытаетесь сделать здесь, то есть получения результатов, которые работают так же, как карандаш-бумажные вычисления с алгоритмами, преподаваемыми в школе.

Экземпляр Decimal, конечно, будет содержать ограниченное количество цифр, которые для 1/3 повторяются бесконечно. Чтобы иметь доступ к цифрам без ограничений, импортируйте fractions и используйте fractions.Fraction(). В этом случае последовательность, создаваемая генератором, будет бесконечной, и вы не сможете преобразовать ее в список, но вы все равно сможете перебирать ее и анализировать столько, сколько вам нужно.

+0

Я попытался «decimal.Decimal (1)», но он сказал: «NameError: глобальное имя« decimal »не определено» – viethaihp291

+0

@ viethaihp291 Вам нужно добавить 'import decimal' в начале вашего скрипта. (То же самое касается 'import fractions', если вы собираетесь с фракциями.) Я теперь обновил ответ, чтобы упомянуть об импорте. – user4815162342

+0

спасибо за разъяснение ... но похоже, что «десятичный» дает только определенное количество знаков после запятой? когда я пытался дать 30 раз, он дает мне ошибку итерации – viethaihp291

0

Я предполагаю, что вы используете Python 3, так как у вас есть только один «/». Вы заметите, что float (1)/3 * 100000000 = 33333333.333333332. Вероятно, это связано с капризами двоичного представления десятичных дробей, потому что у вас заканчивается бит для точности по ширине поплавка.

Таким образом, вы бы лучше его обработки в виде строки, и преобразования, которые в списке:

list(str(float(1)/3))[2:] 

['3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3'] 
0

Вы пытаетесь представить рациональное число как repeating decimal. И вы должны знать, что:

Every rational number is either a terminating or repeating decimal.

Так что вам не нужно хранить все цифры там (не повторяя часть и повторяя часть). Другим важным моментом является то, что если у вас есть m/n, то ваша повторяющаяся часть не должна превышать n-1.

Потому что вы в основном просите разрешения для задачи проекта Euler 26, я его не опубликую, а скорее дам вам link with some explanation.

0

Арифметика с плавающей точкой обязательно неточна. Один из способов точно вычислить цифры - использовать алгоритм деления, который вы, вероятно, узнали в школе.

Вот реализация:

def dec(n): 
    v = 1 
    while v: 
     v *= 10 
     yield v // n 
     v %= n 

Вы можете проверить это, как это, который показывает первые 40 цифр для 1/3, 1/5, 1/7 и 1/11.

import itertools 

for i in [3, 5, 7, 11]: 
    print '1/%d = 0.%s' % (i, ''.join(map(str, itertools.islice(dec(i), 40)))) 

Выход:

1/3 = 0.3333333333333333333333333333333333333333 
1/5 = 0.2 
1/7 = 0.1428571428571428571428571428571428571428 
1/11 = 0.0909090909090909090909090909090909090909