gpt4 book ai didi

python - Numpy 以不同于 python 的方式循环

转载 作者:太空狗 更新时间:2023-10-29 21:57:51 28 4
gpt4 key购买 nike

代码

import numpy as np
a = 5.92270987499999979065
print(round(a, 8))
print(round(np.float64(a), 8))

给予

5.92270987
5.92270988

知道为什么吗?

在 numpy 源中没有发现任何相关内容。

更新:
我知道处理这个问题的正确方法是以这种差异无关紧要的方式构建程序。我做的。我在回归测试中偶然发现了它。

更新2:
关于@VikasDamodar 的评论。人们不应该相信 repr() 函数:

>>> np.float64(5.92270987499999979065)
5.922709875
>>> '%.20f' % np.float64(5.92270987499999979065)
'5.92270987499999979065'

更新3:
在 python3.6.0 x32、numpy 1.14.0、win64 上测试。同样在 python3.6.4 x64、numpy 1.14.0、debian 上。

更新4:
只是为了确定:

import numpy as np
a = 5.92270987499999979065
print('%.20f' % round(a, 8))
print('%.20f' % round(np.float64(a), 8))

5.92270987000000026512
5.92270988000000020435

更新5:
以下代码演示了在不使用 str 的情况下,差异发生在哪个阶段:

>>> np.float64(a) - 5.922709874
1.000000082740371e-09
>>> a - 5.922709874
1.000000082740371e-09
>>> round(np.float64(a), 8) - 5.922709874
6.000000496442226e-09
>>> round(a, 8) - 5.922709874
-3.999999442783064e-09

很明显,在应用“round”之前,它们是相同的数字。

更新6:
与@user2357112 的回答相反,np.round 大约比 round 慢 4 倍:

%%timeit a = 5.92270987499999979065
round(a, 8)

1.18 µs ± 26.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%%timeit a = np.float64(5.92270987499999979065)
round(a, 8)

4.05 µs ± 43.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

此外,在我看来,np.round 比内置的 round 更接近于四舍五入:最初我通过将 11.84541975 除以二得到这个 5.92270987499999979065 数字。

最佳答案

float.__round__使用正确舍入的双字符串算法特别注意生成正确舍入的结果。

NumPy 没有。 NumPy docs提一下

Results may also be surprising due to the inexact representation of decimal fractions in the IEEE floating point standard [R9] and errors introduced when scaling by powers of ten.

这样速度更快,但会产生更多舍入误差。它会导致像您所观察到的错误,以及一些错误,其中数字甚至更明确地低于截止值仍然会被四舍五入:

>>> x = 0.33499999999999996
>>> x
0.33499999999999996
>>> x < 0.335
True
>>> x < Decimal('0.335')
True
>>> x < 0.67/2
True
>>> round(x, 2)
0.33
>>> numpy.round(x, 2)
0.34000000000000002

NumPy 舍入的时间变慢了,但这与哪种舍入算法较慢没有任何关系。 NumPy 与常规 Python 数学之间的任何时间比较都会归结为 NumPy 针对整个数组操作进行了优化的事实。在单个 NumPy 标量上进行数学计算有很多开销,但是使用 numpy.round 舍入整个数组比使用 round 舍入 float 列表要容易得多:

In [6]: import numpy

In [7]: l = [i/7 for i in range(100)]

In [8]: a = numpy.array(l)

In [9]: %timeit [round(x, 1) for x in l]
59.6 µs ± 408 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [10]: %timeit numpy.round(a, 1)
5.27 µs ± 145 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

至于哪个更准确,那肯定是float.__round__。您的数字更接近 5.92270987 而不是 5.92270988,并且它是四舍五入,而不是四舍五入。这里没有领带。

关于python - Numpy 以不同于 python 的方式循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48638398/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com