分配给numpy数组的值并不总是等于指定的值

时间:2013-06-18 15:09:27

标签: python numpy scipy

以下程序导致的值与指定的值不一致:

from scipy.interpolate import splprep, splev, splrep
import numpy as np

pos2indx = lambda vec: vec.round().astype(np.int64)

t = np.linspace(1,3,150)
x = 150+100*np.sin(t) + 5*np.random.randn(len(t))
y = 150+100*np.cos(t) + 5*np.random.randn(len(t))
z = 150+100*np.cos(t)*np.sin(t) + 5*np.random.randn(len(t))

vector_field = np.zeros((x.max()+10,y.max()+10,z.max()+10,3), dtype=np.float64)

out = splprep([x,y,z],u=t,k=3, full_output=1, quiet=1)
tck, t = out[0]
v = np.transpose(splev(t,tck, der=1))
i,j,k = pos2indx(x),pos2indx(y),pos2indx(z)

vector_field[i,j,k,:] += v
print np.sum(np.abs(vector_field[i,j,k,:]-v))

我希望此过程始终打印为零。 但是,有时它不会! 当输出非零时,它有几千个。

我不确定我是否做错了,或者是否有一些错误。

我也将此报告为scipy问题。

溶液:

Pauli Virtanen:“错误在你的代码中:i,j,k向量可以包含两次给定的坐标对。” (https://github.com/scipy/scipy/issues/2581

jorgeca在下面发布了类似的答案。

谢谢!

2 个答案:

答案 0 :(得分:2)

总结一下您的问题,将v添加到零数组然后减去v并不总是会产生一个零数组:

vector_field = np.zeros((x.max()+10,y.max()+10,z.max()+10,3), dtype=np.float64)
vector_field[i,j,k,:] += v
print np.sum(np.abs(vector_field[i,j,k,:]-v))  # sometimes not 0!!

那不可能是对的!

事实上,索引ijk是numpy数组,所以它使用fancy indexing。当三重指数重复时会发生什么?也就是说,对于某些m,n i[m] == i[n]j[m] == j[n]k[m] == k[n]。事实证明,通过implementation detail(可以随时更改),只会分配索引的最后一个三元组(按C顺序),最后vector_field[i,j,k,:]实际上不包含{{1 }}

答案 1 :(得分:1)

问题似乎是由圆形错误引起的。

我使用dtypes 1000float16float32float64对您的代码float96进行了比较。在vector_field中计算了它给出非零答案的次数:

float16: 1000
float32: 1000
float64: 142
float96: 115