2010-04-02 2 views
51

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

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

ответ

89

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

>>> 10.50 - 0.20 
10.300000000000001 

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

'>>> 10.50 - 0.20' в Python 2.7 получить' 10.3'. – Rockallite

+0

Welp, дерьмо. Я буду переносить большое количество данных из своего поля/столбцов FloatField в DecimalField ... – teewuane

+0

Время, когда у нас есть «не использовать плавающие точки за деньги», аналог bobince http://stackoverflow.com/a/1732454/ 604511 – aitchnyu

6

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


На основе Satchmo Project на основе Django есть CurrencyField и CurrencyWidget, на которые стоит обратить внимание.

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

32

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

Джанго Docs Штаты

The FloatField class is sometimes mixed up with the DecimalField class. Although they both represent real numbers, they represent those numbers differently. FloatField uses Python’s float type internally, while DecimalField uses Python’s Decimal type. Read more here .

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

DecimalField:

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

Больше на DecimalField from the Django Docs.

FloatField:

  • Возвращает встроенный типа поплавка,
  • Нет умное округления, и фактически может привести к округлению вопросов, как описано в Сетхах ответа.
  • Не имеет дополнительный вид проверки, что вы получите от DecimalField
  • В базе данных (PostgreSQL), то FloatField сохраняются как «двойная точность» Тип и хранение устанавливаются как «обычный»

Подробнее о FloatField from the Django Docs.

относится к обоим:

  • Оба поля простираются от класса "Поле" и может принять 'пустой',, 'имя' 'нулевой', 'verbose_name', 'primary_key', 'max_length', 'unique', 'unique_for_year', 'options', 'help_text', 'db_column', 'db_tablespace', 'unique' ',' auto_created ',' validators ',' error_messages ', поскольку все поля, которые простираются от поля, будут иметь.
  • Виджет по умолчанию для обоих полей - это TextInput.

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

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

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

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

>>> round(5.685, 2) 
5.68 

Но в этом случае она будет окружать:

>>> round(2.995, 2) 
3.0 

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

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