python - 将 numpy 数组与标量传递给函数会产生不一致的结果

标签 python numpy

我有一个简单的程序来计算函数。

import numpy as np

def fn(n, x0):
    return (np.sin(np.arcsin(x0**0.5)*2**n))**2

n = np.arange(100)

x0 = 0.3
print(fn(n, x0))
print(fn(50, x0))

生成的结果:

[0.3        0.84       0.5376     0.99434496 0.02249224 0.08794536
 0.32084391 0.87161238 0.44761695 0.98902407 0.04342185 0.16614558
 0.55416492 0.98826465 0.04639054 0.17695382 0.58256466 0.97273231
 0.10609667 0.37936067 0.94178461 0.21930545 0.68484228 0.86333333
 0.47195556 0.99685404 0.01254426 0.04954761 0.18837059 0.61154843
 0.95022779 0.18917976 0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.         0.         0.
 0.         0.         0.         0.        ]
0.9931071163166798

两个结果不一致,因为 fn(n, x0) 结果中索引 50(其中 n=50)的元素为零,而对 50< 的函数求值 结果为非零值。为什么会这样?

为什么 f(n, x0) 生成的数组的大多数元素为零?根据数学计算,情况不应该是这样。

最佳答案

请注意,简单地用 float 替换整数在这里并不是一个正确的解决方案。事实上,对于较大的 n,此方法返回的值完全是伪造的。

让我使用 bigfloat 提供任意精度 float 的库来演示这一点。

使用 float64,n = 99、x0 = 0.3 时返回的值

>>> fn(99., 0.3)
0.013782590413701074

约为 0.0138。

现在,我们将使用 1000 位的高精度来计算正确的值。

>>> def fnbig(n, x0):
...     n, x0 = map(bigfloat.BigFloat, (n, x0))
...     return bigfloat.pow(bigfloat.sin(bigfloat.asin(bigfloat.sqrt(x0))*bigfloat.pow(2, n)), 2)
... 
>>> 
>>> bigfloat.setcontext(bigfloat.Context(1000))

请注意,0.3 必须作为字符串输入,因为从文字 0.3 生成的 float64 已经带有太大的错误,无法获得正确的答案。

>>> fnbig('99', '0.3')
BigFloat.exact('0.363780859940401348053691101648398065131477584225708461696799538248050278540782181716110363889498612214432889606382752875154011855764448898240841915231368492158238806206980341185053867226372528105024157964509865633147960964164133657255856469376571664623973084231004713906743471127849494395877727320492003', precision=1000)

这将返回 ~0.364。

为了确保这是正确的,让我们将精度加倍到 2000 位。

>>> bigfloat.setcontext(bigfloat.Context(2000))
>>> 
>>> fnbig('99', '0.3')
BigFloat.exact('0.3637808599404013480536911016483980651314775842257084616967995382480502785407821817161103638894986122144328896063827528751540118557644488982408419152313684921582388062069803411850538672263725281050241579645098656331479609641641336572558564693765716646239730842310047139067975945820088206827783571320258628882284629795545097600685961974610320482001970915733612836861863674071009032317962504679512051859460424746278292327826581975723619660002116915303723311156451829258099225827808017028059470793304713100650332080089174169114171398280313842625628566029927379227478504732491009738418661061753082431884081337', precision=2000)

以精度 1000 和 2000 返回的值本质上是相同的,因此我们可以确信它们是正确的。

相比之下,使用“正常”浮点算术返回的值几乎是一个随机数。

关于python - 将 numpy 数组与标量传递给函数会产生不一致的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53449200/

相关文章:

python - Pyresttest 运行目录中的所有测试

c++ - 编写 Virtualbox 脚本以创建网络

python - Pandas read_excel

python - 如何实例化具有已知系数的 Scikit-Learn 线性模型而不进行拟合

python - 为什么 NumPy reshape() 会创建一个新数组以及为什么顺序可能不被保留?

python - Numpy 矩阵乘法与矩阵数组

python - 没有重复的列表的笛卡尔积

python - Django 中的 db_type (尝试安装 pootle w/mysql)

python - 根据圆的面积更改 numpy 数组中的值

python - 在 numpy 数组的第一行中查找第一个 0