楼层划分如何不根据记录的规则给出结果?
How is floor division not giving result according to the documented rule?
>>> print (12//0.2)
59.0
>>> print(floor(12/0.2))
60
为什么在这种情况下楼层划分不按规则工作?
p.s。这里 Python 将 0.2
视为 floor division
情况下的 0.20000000001
所以
(12/0.2000000001)
导致 59.999999...
并且 floor(59.999999999)
输出 59
但是不知道为什么 python 在 floor division
的情况下将 0.2
视为 0.2000000001
而在 division
的情况下却没有?
之所以12 / 0.2
的结果是60.0,并不是因为0.2被区别对待,而是因为浮点除法的错误抵消了0.2的表示错误。浮点数始终具有相同的值(大于十进制 0.2),但根据操作,这些错误将累积或被取消。
在其他情况下,错误并未完全取消并显示在结果中:
>>> (12 / (0.2 * 0.2)) * 0.2
59.99999999999999
在 CPython 中,这些特定类型的整数除法(float // 第一个参数自动转换后的 float)和相对大小执行如下(完整方法参见 Python's source code):
mod = a % b
result = (a - mod) / b
如果 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
OP也在问浮点除法的错误,这里也是:
值(尾数 * 基数^指数):
12: 1.1000000000000000000000000000000000000000000000000000 * 2^3
0.2: 1.1001100110011001100110011001100110011001100110011010 * 2^(-3)
记住 0.2 并不是真正的 0.2,它是 0.200000000000000011102230246251565404236316680908203125。 12 除以大于 0.2 的值 的结果应该 小于 60.
除以尾数减去指数,得到:
12 / 0.2: 0.1110111111111111111111111111111111111111111111111111111 * 2^6
但是最后 3 位不适合双精度数,尾数(包括符号)只有 53 位,我们目前使用 56。
由于结果从0开始,我们首先归一化,尾数乘以2,指数减1。然后我们必须舍入到最接近的 53 位尾数:
normalised: 1.110111111111111111111111111111111111111111111111111111 * 2^5
rounded: 1.1110000000000000000000000000000000000000000000000000 * 2^5
1.11100000000000000000000000000000000000000000000000000 * 2^5 等于 60。
正确的结果(1.11011111111111111111111111111111111111111111111111111111 * 2^5)和我们可以表示为64位double的最接值]
>>> print (12//0.2)
59.0
>>> print(floor(12/0.2))
60
为什么在这种情况下楼层划分不按规则工作?
p.s。这里 Python 将 0.2
视为 floor division
情况下的 0.20000000001
所以
(12/0.2000000001)
导致 59.999999...
并且 floor(59.999999999)
输出 59
但是不知道为什么 python 在 floor division
的情况下将 0.2
视为 0.2000000001
而在 division
的情况下却没有?
之所以12 / 0.2
的结果是60.0,并不是因为0.2被区别对待,而是因为浮点除法的错误抵消了0.2的表示错误。浮点数始终具有相同的值(大于十进制 0.2),但根据操作,这些错误将累积或被取消。
在其他情况下,错误并未完全取消并显示在结果中:
>>> (12 / (0.2 * 0.2)) * 0.2
59.99999999999999
在 CPython 中,这些特定类型的整数除法(float // 第一个参数自动转换后的 float)和相对大小执行如下(完整方法参见 Python's source code):
mod = a % b
result = (a - mod) / b
如果 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
OP也在问浮点除法的错误,这里也是:
值(尾数 * 基数^指数):
12: 1.1000000000000000000000000000000000000000000000000000 * 2^3
0.2: 1.1001100110011001100110011001100110011001100110011010 * 2^(-3)
记住 0.2 并不是真正的 0.2,它是 0.200000000000000011102230246251565404236316680908203125。 12 除以大于 0.2 的值 的结果应该 小于 60.
除以尾数减去指数,得到:
12 / 0.2: 0.1110111111111111111111111111111111111111111111111111111 * 2^6
但是最后 3 位不适合双精度数,尾数(包括符号)只有 53 位,我们目前使用 56。
由于结果从0开始,我们首先归一化,尾数乘以2,指数减1。然后我们必须舍入到最接近的 53 位尾数:
normalised: 1.110111111111111111111111111111111111111111111111111111 * 2^5
rounded: 1.1110000000000000000000000000000000000000000000000000 * 2^5
1.11100000000000000000000000000000000000000000000000000 * 2^5 等于 60。
正确的结果(1.11011111111111111111111111111111111111111111111111111111 * 2^5)和我们可以表示为64位double的最接值]