我想这是一个经典的浮点精度问题,但我试图围绕这个结果,1//0.01在 Python 3.7.5 中运行yields 99。
我想这是一个预期的结果,但是有什么方法可以决定何时使用int(1/f)而不是更安全1//f?
che*_*ner 24
如果这是与实数的除法,1//0.01则正好是 100。不过,由于它们是浮点近似值,0.01因此略大于 1/100,这意味着商略小于 100。然后是这个 99.something 值到 99。
tri*_*cot 10
这个结果的原因就像你说的,并在浮点数学是否被破坏?以及许多其他类似的问答。
当您知道分子和分母的小数位数时,更可靠的方法是先将这些数字相乘,以便将它们视为整数,然后对它们进行整数除法:
所以在你的情况下1//0.01应该首先转换1*100//(0.01*100)为100。
在更极端的情况下,您仍然可以获得“意想不到”的结果。round在执行整数除法之前,可能需要添加对分子和分母的调用:
1 * 100000000000 // round(0.00000000001 * 100000000000)
Run Code Online (Sandbox Code Playgroud)
但是,如果这是关于使用固定小数(钱,美分),那么考虑使用美分作为单位,以便所有算术都可以作为整数算术完成,并且只在执行时转换为/从主要货币单位(美元)输入/输出。
或者,使用小数库,如decimal,它:
...提供对快速正确舍入十进制浮点运算的支持。
from decimal import Decimal
cent = Decimal(1) / Decimal(100) # Contrary to floating point, this is exactly 0.01
print (Decimal(1) // cent) # 100
Run Code Online (Sandbox Code Playgroud)
你必须考虑到是什么//是floor运营商,因此你首先应该想到,如果你有相同的概率在100下降为99(*)(因为会被操作100 ± epsilon与epsilon>0提供的,恰好100.00的机会..0 非常低。)
你实际上可以看到相同的减号,
>>> 1//.01
99.0
>>> -1//.01
-100.0
Run Code Online (Sandbox Code Playgroud)
你应该(不)感到惊讶。
另一方面,int(-1/.01)首先执行除法,然后int()在数字中应用 ,这不是地板而是向 0 的截断!这意味着在那种情况下,
>>> 1/.01
100.0
>>> -1/.01
-100.0
Run Code Online (Sandbox Code Playgroud)
因此,
>>> int(1/.01)
100
>>> int(-1/.01)
-100
Run Code Online (Sandbox Code Playgroud)
不过,四舍五入会给你这个运算符的预期结果,因为同样,这些数字的误差很小。
(*)我不是说概率是一样的,我只是说当你用浮动算术执行这样的计算时,先验的是你得到的估计。
浮点数不能准确表示大多数十进制数,因此当您键入浮点文字时,您实际上会得到该文字的近似值。近似值可能大于或小于您键入的数字。
您可以通过将浮点数转换为小数或分数来查看浮点数的确切值。
>>> from decimal import Decimal
>>> Decimal(0.01)
Decimal('0.01000000000000000020816681711721685132943093776702880859375')
>>> from fractions import Fractio
>>> Fraction(0.01)
Fraction(5764607523034235, 576460752303423488)
Run Code Online (Sandbox Code Playgroud)
我们可以使用 Fraction 类型来查找由我们的不精确文字引起的错误。
>>> float((Fraction(1)/Fraction(0.01)) - 100)
-2.0816681711721685e-15
Run Code Online (Sandbox Code Playgroud)
我们还可以通过使用 numpy 中的 nextafter 找出 100 左右的双精度浮点数的粒度。
>>> from numpy import nextafter
>>> nextafter(100,0)-100
-1.4210854715202004e-14
Run Code Online (Sandbox Code Playgroud)
由此我们可以推测最接近的浮点数1/0.01000000000000000020816681711721685132943093776702880859375实际上正好是 100。
1//0.01和之间的区别int(1/0.01)是四舍五入。1//0.01 在一个步骤中将精确结果向下舍入到下一个整数。所以我们得到的结果是 99。
另一方面,int(1/0.01) 分两个阶段舍入,首先将结果舍入到最接近的双精度浮点数(正好是 100),然后将该浮点数向下舍入到下一个整数(即又正好是 100)。