我以为这是一个经典的浮点精度问题,但是我试图绕过这个结果,运行 1//0.01用Python 3.7.5 yields99。
我想这是预期的结果,但是有什么方法可以决定何时使用它int(1/f)而不是更安全1//f吗?
round()且从不//或,可以按预期的99.99%进行工作int()。链接的问题是关于浮点数比较与截断无关,也没有如此简单的解决方法。
我以为这是一个经典的浮点精度问题,但是我试图绕过这个结果,运行 1//0.01用Python 3.7.5 yields99。
我想这是预期的结果,但是有什么方法可以决定何时使用它int(1/f)而不是更安全1//f吗?
round()且从不//或,可以按预期的99.99%进行工作int()。链接的问题是关于浮点数比较与截断无关,也没有如此简单的解决方法。
Answers:
如果这是用实数进行的除法,1//0.01则将恰好是100。由于它们是浮点近似值,所以0.01它略大于1/100,这意味着商略小于100。就是这个99.something值然后被下限到99。
导致这种结果的原因就像您陈述的那样,并在浮点数学运算符被破坏吗?中进行了解释。以及许多其他类似的问答。
当您知道分子和分母的小数位数时,一种更可靠的方法是先将这些数字相乘,以便将它们视为整数,然后对它们进行整数除法:
因此,在您的情况下,1//0.01应首先将1*100//(0.01*100)其转换为100。
在更极端的情况下,您仍然可以获得“意外”结果。round在执行整数除法之前,可能有必要添加对分子和分母的调用:
1 * 100000000000 // round(0.00000000001 * 100000000000)
但是,如果这是关于使用固定的小数(货币,美分),那么请考虑将cents作为单位使用,以便所有算术都可以作为整数算术完成,并且仅与主要货币单位(美元)进行相互转换I / O。
或者,也可以使用一个库来存储小数,例如decimal:
...提供对快速正确舍入的十进制浮点算术的支持。
from decimal import Decimal
cent = Decimal(1) / Decimal(100) # Contrary to floating point, this is exactly 0.01
print (Decimal(1) // cent) # 100
您必须要考虑的//是floor操作员,因此您首先应该考虑的是,与99(*)一样,您有同等的概率下降到100(因为操作将100 ± epsilon与epsilon>0只要获得100.00的机会, ..0极低。)
实际上,您可以看到带有减号的内容,
>>> 1//.01
99.0
>>> -1//.01
-100.0
并且您应该感到惊讶。
另一方面,int(-1/.01)先执行除法,然后将int()in 应用于数字,该数字不是下限,而是向0的截断!表示在那种情况下
>>> 1/.01
100.0
>>> -1/.01
-100.0
因此,
>>> int(1/.01)
100
>>> int(-1/.01)
-100
但是,四舍五入将为您提供此运算符的预期结果,因为同样,这些数字的误差很小。
(*)我并不是说概率是相同的,我只是说当您使用浮动算术执行这样的计算时,这是对所获得收益的估计,这是先验的。
浮点数不能完全表示大多数十进制数,因此,当您键入浮点数文字时,实际上可以获得该文字的近似值。近似值可能大于或小于您键入的数字。
通过将浮点数强制转换为十进制或小数,可以查看其确切值。
>>> from decimal import Decimal
>>> Decimal(0.01)
Decimal('0.01000000000000000020816681711721685132943093776702880859375')
>>> from fractions import Fractio
>>> Fraction(0.01)
Fraction(5764607523034235, 576460752303423488)
我们可以使用Fraction类型来查找由于我们的字面量不准确而导致的错误。
>>> float((Fraction(1)/Fraction(0.01)) - 100)
-2.0816681711721685e-15
我们还可以通过使用numpy中的nextafter来找出100左右的粒度双精度浮点数的大小。
>>> from numpy import nextafter
>>> nextafter(100,0)-100
-1.4210854715202004e-14
由此我们可以推测到,最接近的浮点数1/0.01000000000000000020816681711721685132943093776702880859375实际上就是100。
1//0.01和之间的区别int(1/0.01)是四舍五入。1 // 0.01一步将精确结果四舍五入到下一个整数。这样我们得到99的结果。
另一方面,int(1 / 0.01)分两步取整,首先将结果取整为最接近的双精度浮点数(正好为100),然后将浮点数取整为下一个整数(即再次恰好是100)。
int(0.9) == 0和int(-0.9) == 0
如果执行以下
from decimal import *
num = Decimal(1) / Decimal(0.01)
print(num)
输出将是:
99.99999999999999791833182883
这是内部表示的方式,因此将其四舍五入//将得到99
Decimal(0.01)您来不及了,因此在致电之前,该错误已经悄然发生Decimal。我不确定这对问题的答案如何...您必须首先使用来计算精确的0.01 Decimal(1) / Decimal(100),如我在答案中所示。