这是问题的核心,在Python中:
>>> 6/0.05 == 120
True
>>> 6//0.05 == 120
False
6/0.05
的浮点数结果足够接近 120(即在双精度精度范围内),所以它被四舍五入为 120.0。然而,它比 120 稍微小一些,所以显式的地板除法将在将该数字规范化为 120.0 之前将其截断为 119。
以下是一些证明:
>>> from decimal import Decimal
... print(6/Decimal(0.05)) # exactly approximate
... print(6/Decimal('0.05')) # exact
119.9999999999999933386618522
1.2E+2
第一个数字是使用 6/0.05
得到的,但是数字 119.9999999999999933386618522
被舍入为最接近双精度浮点数表示的数字,这个数字是120。可以轻松地证明在双精度内这两个数字确实相同:
>>> print(6/Decimal('0.05') - 6/Decimal(0.05))
6.6613381478E-15
>>> 120 - 6.6613381478E-15 == 120
True
现在,这里有来自MATLAB的
help mod
:
MOD(x,y) returns x - floor(x./y).*y if y ~= 0, carefully computed to
avoid rounding error. If y is not an integer and the quotient x./y is
within roundoff error of an integer, then n is that integer.
这表明当x/y
接近整数时,它会先四舍五入,而不像Python中一样截断。所以MATLAB在浮点数结果方面进行了一些魔法。
最简单的解决方案是自己进行四舍五入(除非你可以使用类似于decimal.Decimal
之类的东西,但这意味着你应该完全放弃本地双精度,包括字面量)并以这种方式复制MATLAB的mod
,假设这对你的用例有意义。
floor_divide
函数互补的余数。np.floor_divide(6, 0.05)=119.0
。119.0*.05=5.95
。因此,你得到的余数值为0.04999999999999967
。 - Aditya6//0.05 == 120
不是吗? - Quang Hoang6//0.05 == 119.0
。它将数字四舍五入到较低的值。 - Aditya