Ответ 1
Всегда используйте DecimalField
за деньги. Даже простые операции (сложение, вычитание) не защищены от проблем округления округления:
>>> 10.50 - 0.20
10.300000000000001
>>> Decimal('10.50') - Decimal('0.20')
Decimal('10.30')
Мне любопытно, какой из них лучше подходит как валютное поле? Я буду делать простые операции, такие как различие, процент между старыми и новыми ценами. Я планирую сохранить две цифры после нуля (т.е. 10.50) и большую часть времени, если эти цифры равны нулю, я буду скрывать эти цифры и отображать их как "10"
ps: Валюта не основана на долларах:)
Всегда используйте DecimalField
за деньги. Даже простые операции (сложение, вычитание) не защищены от проблем округления округления:
>>> 10.50 - 0.20
10.300000000000001
>>> Decimal('10.50') - Decimal('0.20')
Decimal('10.30')
Ответ на вопрос правильный, однако некоторые пользователи могут наткнуться на этот вопрос, чтобы выяснить разницу между DecimalField и FloatField. Проблема округления чисел, которую поднимает Сет, является проблемой для валюты.
Государства Django Docs
Класс FloatField иногда смешивается с классом DecimalField. Хотя они оба представляют действительные числа, они представляют эти числа по-разному. FloatField использует тип чисел с плавающей точкой Pythons, а DecimalField использует десятичный тип Pythons. Подробнее здесь.
Вот другие различия между этими двумя полями:
DecimalField:
<class 'decimal.Decimal'>
Подробнее о DecimalField из Django Docs.
FloatField:
<type 'float'>
Подробнее о FloatField из Django Docs.
Относится к обоим:
Я сталкивался с этим вопросом, когда искал разницу между двумя полями, поэтому думаю, что это поможет тем, кто находится в одной и той же ситуации :)
ОБНОВЛЕНИЕ: Чтобы ответить на вопрос, я думаю, что вы можете выбрать любой из них для представления валюты, хотя десятичная дробь гораздо лучше подходит. Существует проблема с округлением, когда он считается с плавающей точкой, поэтому вы должны использовать 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 больше неактивен, поэтому взгляните на эти альтернативы для обработки валюты
Проект Satchmo на основе Django имеет вид CurrencyField и CurrencyWidget, на который стоит обратить внимание.
Откройте каталог приложений satchmo_utils для источника
Я знаю, что это очень старое, но я наткнулся на это в поисках чего-то совершенно другого, и я хотел бы добавить, что в общем случае не рекомендуется использовать числа с плавающей запятой (с плавающей запятой или десятичное число) для валюты, поскольку математическое округление с плавающей запятой будет неизменно приводят к небольшим ошибкам в расчетах, которые со временем могут привести к очень большим расхождениям.
Вместо этого используйте целочисленное поле или строку по своему усмотрению. Умножьте свою валюту, чтобы переместить десятичную запятую в конец, и сделайте целое число, когда вы сохраните ее, а затем переместите ту десятичную запятую туда, где она должна быть, когда вам нужно ее показать. Это в основном то, как банки (и большинство библиотек валют) обрабатывают хранение данных и в дальнейшем избавят вас от проблем.
Я научился этому нелегко, потому что это не совсем обычная тема; может быть, это спасает кого-то еще от того же.