numpy 为什么np.zeros_like(x)和np.zeros(len(x))的结果不同?

clj7thdc  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(123)

当我使用np.zeros(len(x))np.zeros_like(x)时,我的代码的行为不同
np.zeros(len(x)),我得到了正确的答案:

def discount_cumsum(x: np.ndarray, d):
    # if i use the following line, it works
    y = np.zeros(len(x))

    y[-1] = x[-1]
    for i in range(len(x) - 2, -1, -1):
        y[i] = x[i] + d * y[i + 1]
    return y

discount_cumsum(range(5), 0.5) # array([1.625, 3.25 , 4.5  , 5.   , 4.   ])

字符串
切换到np.zeros_like(x)给出了错误的答案:

def discount_cumsum_2(x: np.ndarray, d):
    # if i use the following line, it doesn't work
    y = np.zeros_like(x)

    y[-1] = x[-1]
    for i in range(len(x) - 2, -1, -1):
        y[i] = x[i] + d * y[i + 1]
    return y

discount_cumsum_2(range(5), 0.5) # array([1, 3, 4, 5, 4])


我期望np.zeros_like(x)np.zeros(len(x))得到给予相同的结果。为什么我得到不同的结果?
对于任何感兴趣的人来说,这就是我一开始想要的。

@numba.njit
def discount_cumsum(x: np.ndarray, d):
    y = x.copy().astype(np.float32)
    for i in range(len(y) - 2, -1, -1):
        y[i] += d * y[i + 1]
    return y

8iwquhpp

8iwquhpp1#

np.zeros_like给你一个零数组,它和参数1有 * 相同的dtype *。当你传递它range(5)时,zeros_like创建一个int s的数组。这是与np.zeros(len(x))的关键区别,它给你一个float s的数组,它的长度和x相同。

>>> a = range(5)
>>> x = np.zeros_like(a)
>>> y = np.zeros(len(a))

>>> print(x.dtype, y.dtype)
int32 float64

字符串
因为你的函数现在有y作为一个 integers 数组,对它的任何操作都是整数操作,如果你有一个浮点数组,你会失去任何精度。
如果你想强制y始终是一个浮点数组,你可以这样做:

y = np.zeros_like(x, dtype=np.float64)


或者,您可以将np.zerosx.shape一起使用(当然,您必须首先确保x是numpy数组):

y = np.zeros(np.asarray(x).shape)


1如果参数不是np.ndarray(因此没有dtype),在使用它的dtype创建零数组之前,它被转换为np.ndarray。在@tdelaney评论的示例中,np.zeros_like([1, 2.1, 'three'])首先将[1, 2.1, 'three']转换为array(['1', '2.1', 'three'], dtype='<U32'),然后返回dtype='<U32'的“零”数组(即空字符串)

相关问题