根据记录的规则,楼层划分如何不给出结果?

Aas*_*jan 9 python floating-point operators division floor-division

>>> print (12//0.2)
59.0
>>> print(floor(12/0.2))
60
Run Code Online (Sandbox Code Playgroud)

在这种情况下,为什么楼层划分不按规则工作?

PS这里Python是治疗0.20.20000000001floor division这样的情况下 (12/0.2000000001)被产生59.999999...floor(59.999999999)输出59 但是不知道为什么Python是治疗0.20.2000000001floor division情况下,但不是在division如此吗?

Die*_*lli 9

之所以 12 / 0.2结果是60.0,不是因为0.2被区别对待,而是因为浮点除法中的错误抵消了0.2的表示中的错误。浮点数始终具有相同的值(大于十进制 0.2),但根据操作,这些错误将累积或取消。

在其他情况下,错误并未完全取消并显示在结果中:

>>> (12 / (0.2 * 0.2)) * 0.2
59.99999999999999
Run Code Online (Sandbox Code Playgroud)

在 CPython 中对这些特定类型的整数除法(float // float 后第一个参数自动转换)和相对大小的执行如下(完整方法请参见Python 的源代码):

mod = a % b
result = (a - mod) / b
Run Code Online (Sandbox Code Playgroud)

如果 b 实际上是 0.2,那么mod它将是 0,但在浮点数中它稍大一些,因此mod略低于 0.2。

如果您手动执行此操作,您可以看到我们最终得到 59.0:

>>> a = 12.0
>>> b = 0.2
>>> mod = a % b
>>> mod
0.19999999999999934
>>> (a - mod) / b
59.0
Run Code Online (Sandbox Code Playgroud)

OP 还询问浮点除法中的错误,这也是:

值(尾数 * 基数^指数):

12:         1.1000000000000000000000000000000000000000000000000000 * 2^3
0.2:        1.1001100110011001100110011001100110011001100110011010 * 2^(-3)
Run Code Online (Sandbox Code Playgroud)

记住 0.2 并不是真正的 0.2,它是 0.200000000000000011102230246251565404236316680908203125。12 除以 > 0.2 的值的结果应该是 < 60。

要对值进行除法,我们将尾数除以减去指数,因此我们得到:

12 / 0.2:   0.1110111111111111111111111111111111111111111111111111111 * 2^6
Run Code Online (Sandbox Code Playgroud)

但是最后 3 位不适合双精度数,它的尾数(包括符号)只有 53 位,而我们目前使用的是 56。

由于结果从 0 开始,我们首先进行归一化,将尾数乘以 2 并从指数中减去 1。然后我们必须四舍五入到最接近的 53 位尾数:

normalised: 1.110111111111111111111111111111111111111111111111111111 * 2^5
rounded:    1.1110000000000000000000000000000000000000000000000000 * 2^5
Run Code Online (Sandbox Code Playgroud)

1.111000000000000000000000000000000000000000000000000 * 2^5 等于 60。

正确的结果(1.110111111111111111111111111111111111111111111111111111 * 2 ^ 5),我们可以表示为64最接近的值之间的差分比特双(1.1110000000000000000000000000000000000000000000000000 * 2 ^ 5)是在浮点除法的误差。