Django: FloatField или DecimalField для валюты?



Мне любопытно, какой из них лучше подходит в качестве валютного поля ? Я буду делать простые операции, такие как взятие разницы, процент между старыми и новыми ценами. Я планирую сохранить две цифры после нуля (т. е. 10.50) и большую часть времени, если эти цифры равны нулю, я буду скрывать эти цифры и отображать их как "10"



ps: валюта не основана на долларах:)

896   4  

4 ответов:

всегда использовать DecimalField деньги. Даже простые операции (сложение, вычитание) не застрахованы от проблем с плавающим округлением:

>>> 10.50 - 0.20
10.300000000000001

>>> Decimal('10.50') - Decimal('0.20')
Decimal('10.30')

ответ на вопрос правильный, однако некоторые пользователи будут натыкаться на этот вопрос, чтобы узнать разницу между DecimalField и FloatField. Проблема с плавающим округлением, которую поднимает сет, является проблемой для валюты.

В Документах Django Говорится

класс FloatField иногда смешивается с классом DecimalField. Хотя они оба представляют реальные числа, они представляют эти числа по-разному. FloatField использует поплавок Python введите внутренне, в то время как DecimalField использует десятичный тип Python. Читать дальше здесь.

вот другие различия между двумя полями:

DecimalField:

  • DecimalFields должны определить атрибут' decimal_places 'и' max_digits'.
  • вы получаете две проверки свободной формы, включенные здесь из вышеуказанных обязательных атрибутов, т. е. если вы установите max_digits в 4, и вы вводите десятичное число, которое равно 4.00000 (5 цифры), вы получите эту ошибку: убедитесь, что в общей сложности не более 4 цифр.
  • вы также получаете аналогичную проверку формы для десятичных знаков (которая в большинстве браузеров также будет проверяться на переднем конце с помощью атрибута step в поле ввода. Если вы установите decimal_places = 1 и введите 0.001 в качестве значения, вы получите ошибку, что минимальное значение должно быть 0.1.
  • возвращает десятичное значение.Десятичное число, тип
  • не имеет лишних проверка как DecimalField
  • с десятичным типом округление также обрабатывается для вас из-за необходимых атрибутов, которые должны быть установлены, как описано выше. Так что из раковины, Если вы
  • в базе данных (postgresql) десятичное поле сохраняется как числовой тип(max_digits, decimal_laces), а хранилище задается как "main", из приведенного выше примера тип является числовым(4,1)

подробнее о десятичное поле из Джанго Документы.

FloatField:

  • возвращает встроенный тип float,
  • нет интеллектуального округления и фактически может привести к проблемам округления, как описано в ответе Seths.
  • не имеет дополнительной проверки формы, которую вы получаете от DecimalField
  • в базе данных (postgresql) поле FloatField сохраняется как тип "двойная точность", а хранилище устанавливается как "простое"

подробнее о FloatField from в Джанго документы.

применяется как:

  • оба поля простираются от "полевых" класса и может принимать 'пустой', 'нуль', 'verbose_name', 'имя', 'primary_key', 'max_length', 'уникальный', 'db_index', 'отн', 'по умолчанию', 'редактировать', 'сериализации', 'unique_for_date', 'unique_for_month', 'unique_for_year', 'выбор', 'help_text', 'db_column', 'db_tablespace', 'auto_created', 'валидаторов, атрибуты error_messages, а всех полей, которые простираются от "поле" будет иметь.
  • виджет формы по умолчанию для обоих полей-это TextInput.

я столкнулся с этим вопросом, когда искал разницу между двумя полями, поэтому я думаю, что это поможет тем, кто находится в той же ситуации :)

UPDATE: чтобы ответить на вопрос, я думаю, что вы можете уйти с любой из них, чтобы представлять валюту, хотя десятичное число гораздо лучше подходит. Существует проблема округления, когда он рассчитывает плавать, так что вы должны использовать round(value, 2) для того, чтобы сохранить ваш представление с плавающей запятой округляется до двух знаков после запятой. Вот краткий пример:

>>> round(1.13 * 50 + .01, 2)
56.51

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

>>> round(5.685, 2)
5.68

но в этом случае, он будет сгонять:

>>> round(2.995, 2)
3.0

Это все связано с тем, как поплавок хранится в памяти. Смотрите здесь.

edit: проект Satchmo больше не активен, поэтому взгляните на эти альтернативы для обработки валюты


основанным на Django Проект Сатчмо есть валюта и CurrencyWidget, которые стоит посмотреть.

Проверьте каталог приложений satchmo_utils для источника

Я знаю, что это супер старый, но я наткнулся на него, ища что-то совершенно другое, и я хотел выбросить там, что вообще нецелесообразно использовать числа с плавающей точкой (float или decimal) для валюты, поскольку математическое округление с плавающей запятой неизбежно приведет к небольшим ошибкам в вычислениях, которые могут привести к очень большим расхождениям во времени.

вместо этого используйте целочисленное поле или строку по своему усмотрению. Умножьте свою валюту, чтобы переместить десятичное число до конца и сделать целое число, когда вы храните его, а затем переместить этот десятичный знак обратно, где он принадлежит, когда вам нужно, чтобы показать его. Это в основном то, как банки (и большинство библиотек валют) обрабатывают хранение данных и впоследствии избавят вас от множества проблем.

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

Comments

    Ничего не найдено.