django中的货币字段是浮点字段+圆()吗?

时间:2014-10-19 03:56:17

标签: python django floating-point decimal

我很喜欢在我的django项目中使用浮动字段作为货币。我刚刚用python float了解了这个舍入问题:

>>> 0.1 + 0.2 - 0.3
5.551115123125783e-17

现在我有两个选择:

  1. 使用South将所有浮动字段迁移到十进制字段,这是一个很大的痛苦。
  2. 在每次加法和减法后执行round()以在保存之前获得正确的结果。毕竟,我的应用程序中的所有货币字段只允许1位小数。
  3. 我的问题是,如果我正在处理的是添加和减去100.0和1.2之类的数字,那么选项2是否正常?除了舍入误差之外还有什么可担心的吗?

3 个答案:

答案 0 :(得分:1)

小心round(); round(0.1+0.2-0.3+1.2)会给你1.0,而不是1.2。您需要使用Decimal,然后将其正确转换为float:

>>> r = Decimal('0.1') + Decimal('0.2') - Decimal('0.3')
>>> r
Decimal('0.0')
>>> float(r)
0.0
>>> round(0.1+0.2-0.3+1.2)
1.0
>>> r = Decimal('0.1') + Decimal('0.2') - Decimal('0.3') + Decimal('1.2')
>>> r
Decimal('1.2')
>>> float(r)
1.2

这也将处理你需要手动处理的边缘情况,应该采用float()+ round()方法。

最后,不要混淆值的打印方式与存储方式。 “只允许1位小数” - 这是一个演示细节。

答案 1 :(得分:1)

使用decimal字段(使用decimal.Decimal)在Python中准确处理货币:

>>> from decimal import Decimal as D
>>> D('0.1') + D('0.2') - D('0.3')
Decimal('0.0')
>>> assert _ == 0

答案 2 :(得分:1)

要清楚,问题不在于Python的浮点数,而是浮点数的二进制表示 - 对于容易用十进制表示的数字,它通常不准确。

一般来说,我同意你应该使用Decimal类的其他答案,因为它是为浮点数的精确表示而设计的(以空间为代价+数学运算的效率)。另一种选择,如果你确切地知道你的精确度(正如你所说,一旦小数点)将使用整数作为定点数。您将1.3存储为13并且只知道在显示之前需要将其移动一位小数。但是使用Decimal更简洁,代码可能更具可读性。