其实,这是不正确的
3.5 % 0.1是
0.1。您可以很容易地对此进行测试:
>>> print(3.5 % 0.1)0.1>>> print(3.5 % 0.1 == 0.1)False
实际上,在大多数系统上
3.5 %0.1是
0.099999999999999811。但是,在某些版本的Python上
str(0.099999999999999811)是
0.1:
>>> 3.5 % 0.10.099999999999999811>>> repr(3.5 % 0.1)'0.099999999999999811'>>> str(3.5 % 0.1)'0.1'
现在,您可能想知道为什么
3.5 %0.1是
0.099999999999999811而不是
0.0。这是由于通常的浮点舍入问题。如果您还没有阅读每位计算机科学家应该知道的有关浮点运算的知识,则应该-
至少是Wikipedia对该问题的简要概述。
还需要注意的是
3.5/0.1不是
34,它的
35。那么,
3.5/0.1 * 0.1 +3.5%0.1是
3.5999999999999996,这是不甚至 接近
到
3.5。这对于模数的定义非常重要,在Python和几乎所有其他编程语言中都是错误的。
但是Python 3在那里抢救了。大多数了解的人都知道
//这是如何在整数之间进行“整数除法”,但没有意识到这是您如何在 任何
类型之间进行模数兼容的除法。
3.5//0.1是
34.0,
3.5//0.1 * 0.1 +3.5%0.1(至少舍入误差很小)
3.5。它已被反向移植到2.x,因此(取决于您的确切版本和平台),您也许可以依靠此。而且,如果没有,则可以使用
divmod(3.5,0.1),它返回(在舍入误差内)
(34.0, 0.09999999999999981)一直回到时间的迷雾中。当然,您仍然希望这是
(35.0,0.0),而不是
(34.0, almost-0.1),但是由于舍入错误,您不能拥有它。
如果您正在寻找快速修复,请考虑使用以下
Decimal类型:
>>> from decimal import Decimal>>> Decimal('3.5') % Decimal('0.1')Decimal('0.0')>>> print(Decimal('3.5') % Decimal('0.1'))0.0>>> (Decimal(7)/2) % (Decimal(1)/10)Decimal('0.0')这不是魔术般的灵丹妙药-例如,每当操作的确切值在基数10中不能无限表示时,您仍将不得不处理舍入错误-
但是舍入错误更符合人类直觉期望的情况有问题。(
Decimalover的另一个优点
float是,您可以指定显式精度,跟踪有效数字等,并且在从2.4到3.3的所有Python版本中实际上都是相同的,而有关详细信息同时
float已更改了两次。但是,当您事先知道所有数字都可以精确地以10为基数表示,并且它们不需要比您配置的精度高的数字时,它就会起作用。



