numpy 数组元数据更改

numpy array metadata change

我知道 numpy 在连续内存中存储数字。那么可以拿

a = np.array([127,127,127,127,127,127,127,127], dtype=np.uint8)

'a'的二进制表示都是全1

对此:

b = np.array([72057594037927935], dtype=np.uint64)

以及从 b->a 返回。

二进制表示全部为1,但是元素的数量组合为一个64位int 在 Numpy 中表示应该相同,只有元数据应该改变。

这听起来像是一项跨步技巧的工作,但我的最佳猜测是:

np.lib.stride_tricks.as_strided(a, shape=(1,), strides=(8,8))

np.lib.stride_tricks.as_strided(b, shape=(8,), strides=(1,8))

只得到 ValueError:步幅长度和形状不匹配

这里只需要阅读,所以我没有妄想我需要更改数据。

如果您想重新解释 数组中的现有数据,您需要numpy.ndarray.view。这是 .astype.view 之间的主要区别(即前者转换为保留 values 的新类型,而后者保持相同的内存和变化它是如何解释的):

import numpy as np 

a = np.array([127,127,127,127,127,127,127,127], dtype=np.uint8)
b = a.view(np.uint64) 
print(a) 
print(b) 
print(b.view(np.uint8))                                        

这输出

[127 127 127 127 127 127 127 127]
[9187201950435737471]
[127 127 127 127 127 127 127 127]

请注意 127 在其二进制模式中有一个前导零,所以它 不是 全一,这就是我们在 b 中得到的值的原因与您期望的不同:

>>> bin(b[0])
'0b111111101111111011111110111111101111111011111110111111101111111'

>>> bin(72057594037927935)
'0b11111111111111111111111111111111111111111111111111111111'

您似乎假设的是一组 uint7 个位的值...

无论如何,.view 最好的部分是将使用完全相同的内存块,除非您明确复制:

>>> b.base is a
True

推论当然是变异 b 会影响 a:

>>> b += 3

>>> a
array([130, 127, 127, 127, 127, 127, 127, 127], dtype=uint8)

要控制字节顺序,您需要使用 string-valued dtype specifications,即 a.view('<u8')(小端)或 a.view('>u8')(大端)。我们可以用它来重现您问题中的错误号码:

>>> a2 = np.array([0] + [255] * 7, dtype=np.uint8)
... a2.view('>u8')
array([72057594037927935], dtype=uint64)