Django:FloatField还是DecimalField for Currency?

Hel*_*nar 66 django django-models

我很好奇哪一个更适合作为货币领域?我会做一些简单的操作,比如差价,新旧价格之间的百分比.我计划在零(即10.50)之后保留两位数,如果这些数字为零,则保留大部分时间,我将隐藏这些数字并将其显示为"10"

ps:货币不是基于美元:)

Set*_*eth 114

总是用DecimalField钱.即使是简单的操作(加法,减法)也不能免于浮动舍入问题:

>>> 10.50 - 0.20
10.300000000000001

>>> Decimal('10.50') - Decimal('0.20')
Decimal('10.30')
Run Code Online (Sandbox Code Playgroud)

  • Python 2.7中的`>>> 10.50 - 0.20`得到`10.3`. (5认同)
  • 威尔普,废话.我将把我的FloatField字段/列中的大量数据迁移到DecimalField ... (5认同)

rad*_*tek 48

这个问题的答案是正确的,但有些用户会偶然发现这个问题,找出DecimalField和FloatField之间的区别.Seth提出的浮动舍入问题是货币问题.

Django Docs States

FloatField类有时与DecimalField类混合在一起.虽然它们都代表实数,但它们以不同的方式表示这些数字.FloatField在内部使用Python的float类型,而DecimalField使用Python的Decimal类型.在这里阅读更多.

以下是两个字段之间的其他差异:

DecimalField:

  • DecimalFields必须定义'decimal_places'和'max_digits'属性.
  • 你来到这里,从上述要求的属性,即包括两个自由表单验证如果设置max_digits 4,和你在一个十进制是4.00000(5位)类型,您将收到此错误:确保有不超过4总数.
  • 您还可以对小数位进行类似的表单验证(在大多数浏览器中也会使用输入字段上的step属性在前端验证.如果设置decimal_places = 1并输入0.001作为值,则会出现错误最小值必须为0.1.
  • 返回decimal.Decimal,类型为
  • 没有额外的验证作为DecimalField
  • 对于Decimal类型,由于需要如上所述设置的属性,还会为您处理舍入.所以从shell开始,如果你
  • 在数据库(postgresql)中,DecimalField保存为数字(max_digits,decimal_laces)类型,而Storage设置为"main",从上面的示例中Type是数字(4,1)

更多关于Django Docs的DecimalField.

FloatField:

  • 返回内置的float类型,
  • 没有智能舍入,实际上可能导致舍入问题,如Seths回答中所述.
  • 没有从DecimalField获得的额外表单验证
  • 在数据库(postgresql)中,FloatField保存为"双精度"类型,存储设置为"普通"

有关Django Docs的FloatField的更多信息.

适用于两者:

  • 这两个字段从"字段"类扩展,并且可以接受"空白","空","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' 属性,因为从"Field"扩展的所有Fields都有.
  • 两个字段的默认表单窗口小部件是TextInput.

我在寻找两个字段之间的差异时遇到了这个问题所以我认为这将有助于那些处于同样情况的人:)

更新:为了回答这个问题,我认为你可以用任何一种来代表货币,尽管十进制更适合.当计算浮点数时会出现舍入问题,因此必须使用<class 'decimal.Decimal'>以便将浮点表示舍入到小数点后两位.这是一个简单的例子:

>>> round(1.13 * 50 + .01, 2)
56.51
Run Code Online (Sandbox Code Playgroud)

漂浮和圆形你仍然可以遇到麻烦.就像在这里我们看到它向下舍入值5:

>>> round(5.685, 2)
5.68
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,它会围绕:

>>> round(2.995, 2)
3.0
Run Code Online (Sandbox Code Playgroud)

它与浮点数如何存储在内存中有关.看到这里.


Nat*_*Cox 11

我知道这太旧了,但我偶然发现它在寻找完全不同的东西,我想在那里扔掉一般来说不建议使用浮点数(浮点数小数)作为货币,因为浮点数学四舍五入会总是会导致计算中的小错误,随着时间的推移,这些错误可以累积成非常大的差异。

相反,根据您的喜好使用整数字段或字符串。乘以您的货币以将小数位移到末尾并在存储时生成一个整数,然后在需要显示时将该小数位移回它所属的位置。这基本上是银行(和大多数货币库)处理存储数据的方式,并且会在以后为您节省大量麻烦。

我通过艰难的方式学到了这一点,因为它不是一个真正的常见话题;也许这可以避免其他人做同样的事情。


sxa*_*der 6

编辑:Satchmo项目不再有效,因此请查看这些替代方案以处理货币


基于Django的Satchmo项目有一个CurrencyField和CurrencyWidget,值得一看.

查看源的satchmo_utils app目录