为什么 a//b 和 np.floor(a/b) 会产生不同的结果?

问题描述 投票:0回答:3

我使用

//
偶然发现了 python 3 的“地板划分”的奇怪边缘行为。经过一番计算,我得出了公式
(a1 - a2) // b
。使用

a1 = 226.72560000000001
a2 = 0.2856000000000165
b = 1.02
# all types are np.float64

我得到了与我使用时不同的结果

np.floor()

>>> (a1 - a2) // b
221.0
>>> np.floor((a1 - a2) / b)
222.0

这种差异显然源于浮点计算,但为什么它们的行为不同呢?使用更高精度的计算器,例如 ke!san,我可以验证

//
的行为在数学上是正确的,而对于我的计算,
np.floor()
将提供正确的结果。

python python-3.x numpy floating-point precision
3个回答
2
投票

确实

//
行为在数学上是正确的。

但是如果你只是这样做

(a1 - a2) / b
,你可以看到结果已经四舍五入为
222.0
(由于浮动存储限制,它应该是
221.9999999999999936275
),所以现在使用floor将返回
222.0

编辑:实际上对于

//
,首先a1-a2四舍五入为
226.44
,然后由于@Talha Tayyab解释,
226.44 // 1.02
错误地返回
221
而不是
222
(x//y返回(x-x%y) )//y).
因此,有两个连续的舍入,相互补偿并得出正确的结果。


1
投票

如果 x 非常接近 y 的精确整数倍,则由于舍入,x//y 可能比 (x-x%y)//y 大 1。在这种情况下,Python 返回后一个结果,以保持 divmod(x,y)[0] * y + x % y 非常接近 x

文档链接:

https://docs.python.org/3/reference/expressions.html#id10

应该输出什么:

3.3//1.1

3.0 right?

wrong it is 2.0

所以,当分子非常接近分母的倍数时

x//y
将会回来
(x-x%y)//y
:

a1 = 226.72560000000001
a2 = 0.2856000000000165
b = 1.02

x = a1-a2
y = 1.02

(x-x%y)//y

#output
221.0

-1
投票

请记住,浮点运算可能很棘手,但意识到它的陷阱总是一个好主意。这不是 Python 或 NumPy 中的错误,而是浮点数及其算术运算的本质。

您所看到的行为是由于不同浮点类型之间的准确度对比造成的。

术语“漂移点”指的是这些数字在内部的表达方式。微妙的元素非常专业,但关键是这些数字是使用固定数量的位数来表示的,位数越多,获得的准确性就越高。

Python 中(或 NumPy 等库)中的各种浮点数,例如 float16、float32 和 float64,分别指的是使用 16、32 和 64 位的浮点数。

float64(也称为“双重精度漂移”)比 float32(“单精度漂移”)具有更高的精度和更大的运行范围,而 float32 又比 float16(“半精度浮点”)具有更高的精度和更大的范围。

因此,在使用不同的浮点排序执行相同的计算后,由于这些准确性的差异,您会得到一些不同的结果。通常是数值计算中的常见问题,需要注意。

必须为您的特定使用情况选择正确类型的浮点数。一般来说,float64 可能是一个很好的默认选择,因为它在精度和内存利用率之间提供了很大的调整。但是,如果您正在处理异常庞大的数据集,并且内存利用率可能是一个问题,或者如果您正在支持 float32 或 float16 计算的 GPU 上执行计算,那么此时它可能是有意义的利用较低精度的漂移排序。

这里有一些代码可以告诉你原因

这里有一些代码可以告诉你原因:

import numpy as np

a1 = np.float16(226.72560000000001)
a2 = np.float16(0.2856000000000165)
b = np.float16(1.02)

a3= float(226.72560000000001)
a4 = float(0.2856000000000165)
b1 = float(1.02)

print((a3 - a4) // b1)
print((a1 - a2) // b)

print(np.floor((a3 - a4) / b1))
print(np.floor((a1 - a2) / b))

输出:

221.0
222.0
222.0
222.0

您可以更改浮动类型以查看它如何影响结果。

© www.soinside.com 2019 - 2024. All rights reserved.