NumPy:使用自身修改数组时的错误结果

时间:2014-09-04 08:29:08

标签: python arrays numpy undefined-behavior

import numpy as np
bc = np.arange(10) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# regular way using NumPy function
np.diff(bc) # array([1, 1, 1, 1, 1, 1, 1, 1, 1])

# something similar with array subtraction:
bc[1:] - bc[:-1] # array([1, 1, 1, 1, 1, 1, 1, 1, 1])

# but this does the wrong thing:
bc[1:] -= bc[:-1] # array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5])

作为一名C和C ++程序员,我可以理解为什么会发生这种情况(它重新是memcpy()而不是memmove()),但似乎Python和NumPy的最终用户可能并不期望这样。我没有找到任何文件说这不起作用。

问题是:NumPy中是否存在错误(可能没有),或者是否有一些NumPy文档解释了这种情况下的规则是什么,或文档中是否缺少这些规则?

其次,我想找出一种安全,有效的解决方案,它在空间和时间上都是准最佳的。也就是说,它不应该分配超出恒定量的内存,它不应该是一个愚蠢的纯Python“for”循环。 :)这些是人们可能希望通过就地修改实现的目标,这显然不起作用。

我正在使用NumPy 1.8.0。

3 个答案:

答案 0 :(得分:1)

我再次在这里发帖以纠正我的回答。 也许试试:

bc-=np.roll( bc , 1 )

#array([-9,  1,  1,  1,  1,  1,  1,  1,  1,  1])
#this arrays length is 10

#and then for an array with length 9
bc=bc[ 1 : ]  

#array([1,  1,  1,  1,  1,  1,  1,  1,  1])

抱歉错过了之前的问题,

结果的原因:

'array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5])'

此操作实际上被语法化为

的推论
let (say...) a=array([0,1,2,3,4,5,6,7,8,9])
updated a <- will be formed as [0, 1-0=1,2-1=1,3-1=2,4-2=2,5-2=3,6-3=3,7-3=4,8-4=4,9-4=5] 

我认为你真正想要的是

tnx EdChum

答案 1 :(得分:0)

我不认为这是一个错误:
在执行操作时执行bc[1:] -= bc[:-1]您正在修改列表。

这个过程就像

for i in range(1,len(bc)):
    bc[i] = bc[i] - bc[i-1]

因此修改了下一步bc[i-1]

"i"      1
bc[1:]:  1,2,3,4,5,…
bc[:-1]: 0,1,2,3,4,5,… 
bc[1]= 1 - 0 = 1
new bc: 0,1,2,3,4,5,…

"i"        2
bc[1:]:  1,2,3,4,5,…
bc[:-1]: 0,1,2,3,4,5,… 
bc[2]= 2 - 1 = 1
new bc: 0,1,1,3,4,5,…


"i"          3
bc[1:]:  1,1,3,4,5,…
bc[:-1]: 0,1,1,3,4,5,… 
bc[1]= 3 - 1 = 2
new bc: 0,1,1,2,4,5,…


"i"            4
bc[1:]:  1,1,2,4,5,…
bc[:-1]: 0,1,1,2,4,5,… 
bc[1]= 4 - 2 = 2
new bc: 0,1,1,2,2,5,…

等等。

对于其余问题,我无法回答。

答案 2 :(得分:0)

我在发布此问题后确实找到了一些讨论。搜索的重要术语是“切片”。就在这里:http://numpy-discussion.10968.n7.nabble.com/Strange-behavior-in-setting-masked-array-values-in-Numpy-1-1-0-td11999.html

在页面的中间部分有关于试图检测和警告这类事情的讨论,但这听起来像是一个失败的原因。所以我开始寻找另一种就地方法来做我想做的事情。在这里!

bc[-1:0:-1] -= bc[-2::-1]

归功于@fredtantini明确写出NumPy有效的纯Python“for”循环。这让我想到如何在纯Python中修复它(向后迭代!),这导致了上述解决方案。