2014-01-18 7 views
0

Я не имею в виду точность, как в том, сколько чисел отображается после десятичного числа. Я имею в виду точность, как в десятичном значении, которое я пытаюсь использовать в этой функции пиктограммы, продолжает подниматься на одну десятую застенчивее того, что должно быть. Я попытался использовать несколько разных стратегий, включая импорт десятичного модуля. Вот функция, которую я пытаюсь использовать.Точность десятичных знаков в Python

values = [('tens', 10), ('fives', 5), ('ones', 1), ('tenths', 0.1)] 

def get_digits(num): 
    num = int(num * 10) 
    num = float(num)/10 

    output_dict = {} 
    for place, value in values: 
     output_dict[place] = int(num // value) 
     num = num % value 

    return output_dict 

с использованием get_digits(277.9), дает {'tens': 27, 'ones': 2, 'tenths': 8, 'fives': 1}

мне нужно для того, чтобы сказать {'tens': 27, 'ones': 2, 'tenths': 9, 'fives': 1}

Крепление его путем добавления 1 к десятым после того, как словарь заселенных не работает, потому что не каждый десятичный выходит нечетко.

get_digits(277.6) возвращает {'fives': 1, 'tenths': 6, 'tens': 27, 'ones': 2}

Я обыскивал форумы для ответа, но ничего толком не получает его. Будем очень благодарны любой помощи.

+0

Это просто результат использования чисел с плавающей запятой и неспособность компьютера * прекрасно хранить их. См. [1] (http://en.wikipedia.org/wiki/Floating_point), [2] (http://docs.python.org/3/tutorial/floatingpoint.html). Если вам нужна точность, используйте целые числа с фиксированной точкой. – jedwards

+0

Итак, я просто мечтаю с точки зрения возможности делать то, что я пытаюсь сделать? –

+0

Если неточные поплавки действительно являются проблемой, то использование decimal.Decimal() должно помочь, поскольку они точно хранят базовые 10 чисел. Вы также можете попробовать фракции. Fraction(). – dstromberg

ответ

4

Как я попытался объяснить в комментариях, проблема в том, что вы используете числа с плавающей запятой.

Дополнительную информацию о плавающей запятой см. 1, 2.

Вопрос заключается в том, что 277.9не на самом деле хранится как 277.9, а что-то «очень близко»:

print('%.40f' % a) 
277.8999999999999772626324556767940521240234 

Решение не использовать некоторые произвольные эвристики сказать, является ли математика немного и попробуйте исправить это. We знаю Математика немного выключена - это подарок и проклятие, данное нам с плавающей запятой.

Настоящим решением является использование математики с фиксированной точкой, например, с модулем decimal Python.


Редактировать

from decimal import Decimal 

values = [ 
    ('tens', Decimal(10)), 
    ('fives', Decimal(5)), 
    ('ones', Decimal(1)), 
    ('tenths', Decimal('0.1')) 
] 

def get_digits(num): 
    output_dict = {} 
    for place, value in values: 
     output_dict[place] = int(num // value) # Cast from Decimal to int 
     num = num % value 
    return output_dict 

num = Decimal('277.9') 
print(get_digits(num)) 
# {'tens': 27, 'ones': 2, 'tenths': 9, 'fives': 1} 

num = Decimal('277.6') 
print(get_digits(num)) 
#{'tens': 27, 'ones': 2, 'tenths': 6, 'fives': 1} 

Приведенный выше код очень похож на ваш, но использует десятичную модуль Питона. Эвристическая проверка не требуется. Код просто работает, потому что десятичные знаки представлены точно.

+0

Математика с фиксированной точкой все еще может иметь ошибки точности - во всяком случае, она более подвержена ошибкам, чем с плавающей запятой. Десятичный модуль Python хорош для хранения базовых 10 чисел, поскольку реализация десятичного десятилетия также является базой 10. – dstromberg

+0

Я согласен, что фиксированная точка может иметь ошибки точности, но в отличие от представления с плавающей запятой, представление фиксированной точки позволяет пользователю задавать точность. Более того, этот вопрос представляется особенно подходящим для представления фиксированной точки, поскольку он имеет дело с модульной арифметикой базы 10. Эти числа никогда не могут быть сохранены точно в представлении с плавающей запятой, но всегда будут храниться точно в фиксированной точке (при условии достаточной точности). – jedwards

+0

Спасибо. Оба объяснения помогли мне понять больше. –

Смежные вопросы