Django:FloatField还是DecimalField for Currency?

时间:2010-04-02 20:28:57

标签: django django-models

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

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

4 个答案:

答案 0 :(得分:107)

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

>>> 10.50 - 0.20
10.300000000000001

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

答案 1 :(得分:44)

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

Django Docs States

  

FloatField类有时与DecimalField类混合在一起。虽然它们都代表实数,但它们以不同的方式表示这些数字。 FloatField在内部使用Python的float类型,而DecimalField使用Python的Decimal类型。   阅读更多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的额外验证
  • 对于Decimal类型,由于需要如上所述设置的属性,还会为您处理舍入。所以从shell开始,如果你
  • 在数据库(postgresql)中,DecimalField保存为数字(max_digits,decimal_laces)类型,而Storage设置为" main",从上面的示例中Type是数字(4,1)

更多关于DecimalField from the Django Docs

FloatField:

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

更多关于FloatField from the Django Docs

适用于两者:

  • 这两个字段都来自" Field"类,可以接受空白',' null',' verbose_name',' name',' primary_key',& #39; max_length',' unique',' db_index',' rel','默认','可编辑&# 39;,'序列化',' unique_for_date',' unique_for_month',' unique_for_year','选择',&# 39; help_text',' db_column',' db_tablespace',' auto_created','验证器',' error_messages&#39 ;属性,因为所有字段都从"字段"会有。
  • 这两个字段的默认表单窗口小部件是TextInput。

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

更新:要回答这个问题,我认为你可以侥幸地代表货币,尽管十进制更适合。当它计算浮动时存在舍入问题,因此您必须使用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

答案 2 :(得分:6)

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


基于Django的Satchmo Project有一个CurrencyField和CurrencyWidget,值得一看。

查看satchmo_utils app目录中的源

答案 3 :(得分:3)

我知道这是超级老,但我偶然发现它寻找完全不同的东西,我想扔掉那里通常不建议使用浮点数(float 十进制)对于货币,因为浮点数学舍入将总是导致计算中的小错误,这可能会导致长时间内出现非常大的差异。

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

我学到了很多,因为这不是一个常见的话题;也许这可以拯救别人做同样的事情。