我很喜欢在我的django项目中使用浮动字段作为货币。我刚刚用python float了解了这个舍入问题:
>>> 0.1 + 0.2 - 0.3
5.551115123125783e-17
现在我有两个选择:
我的问题是,如果我正在处理的是添加和减去100.0和1.2之类的数字,那么选项2是否正常?除了舍入误差之外还有什么可担心的吗?
答案 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更简洁,代码可能更具可读性。