以下代码片段结果为6:
import math
number = (1 - 0.99) * 500
math.ceil(number)
虽然(数学上)正确的答案是5.可能这是一个舍入问题 - 执行正确解决方案的最佳方法是什么?
答案 0 :(得分:3)
据推测这是一个舍入问题
是:
>>> 1 - 0.99
0.010000000000000009
>>> (1 - 0.99) * 500
5.000000000000004
执行正确解决方案的最佳方法是什么?
您可以使用decimal.Decimal
代替float
:
>>> from decimal import Decimal
>>> import math
>>> (1 - Decimal("0.99")) * 500
Decimal('5.00')
>>> math.ceil((1 - Decimal("0.99")) * 500)
5.0
答案 1 :(得分:2)
这是一个浮点错误,因为有些数字无法准确表示(无限多个数字必须使用有限数量的位来表示 - 必须进行一些权衡)。这就是浮点运算失去一些精度的原因:
>>> 1-0.99
0.010000000000000009
尝试十进制:
>>> from decimal import Decimal as d
>>> result = (1 - d("0.99")) * 500
>>> result
Decimal('5.00')
>>> math.ceil(result)
5.0
修改强>
看起来所有数字都有精确的表示形式:
>>> a = 1.0; b = 0.99; c = 0.01
>>> a, b, c
(1.0, 0.99, 0.01)
所以这个结果可能看起来很令人惊讶:
>>> a - b
0.010000000000000009
>>> a - b == c
False
但这只是累积的精度和舍入误差。以下是相同的数字和计算,但显示更多数字:
>>> def o(f): return "%.30f" % f
>>> o(a)
'1.000000000000000000000000000000'
>>> o(b)
'0.989999999999999991118215802999'
>>> o(c)
'0.010000000000000000208166817117'
>>> o(a-b)
'0.010000000000000008881784197001'
答案 2 :(得分:0)
Python 2.7舍入到17位有效数字。它是真实数学的不同模型。
答案 3 :(得分:0)
给定的答案是正确的,这是舍入错误的情况。但是,我认为包括为什么会发生这种情况会很有用。
在硬件中,浮点数是基数2(AKA二进制)。问题是大多数小数部分不能完全表示为binary fractions。它的转换(通常)浮点数仅由实际存储在机器中的二进制浮点数近似。