【问题标题】:Numpy pack bits into 32-bit little-endian valuesNumpy 将位打包成 32 位 little-endian 值
【发布时间】:2021-05-09 10:34:00
【问题描述】:

Numpy 提供packbits 函数将值转换为单个位。使用 bitorder='little' 我可以在 C 中将它们读取为 uint8_t 值而不会出现问题。但是,我想将它们读取为 uint32_t 值。这意味着我必须颠倒每 4 个字节的顺序。 我尝试使用

import numpy as np

array = np.array([1,0,1,1,0,1,0,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,1,0,1, 
   1,0,0,1,1,0,1,0,1,1,0,0,1,1,1,0,0,1])
array = np.packbits(array, bitorder='little')
array.dtype = np.uint32
array.byteswap(inplace=True)

print(array)

但出现以下错误:

Traceback (most recent call last):
  File "sample.py", line 5, in <module>
    array.dtype = np.uint32
ValueError: When changing to a larger dtype, its size must be a divisor of the total size in bytes of the last axis of the array.

我在输入中有 50 位。以 little-endian 格式写入的第一个 32 位块(最早的输入位是最低有效位)是0b10101001101011001101001010101101 = 2846675629,第二个是0b100111001101011001 = 160601。所以预期的输出是

[2846675629 160601]

【问题讨论】:

  • @Curious 以后,请提供完整错误堆栈跟踪,而不仅仅是底线。它将帮助人们更快地帮助您,并将大大减少您的问题被关闭的机会。还包括预期输出。
  • 期望的输出是什么?
  • 另请注意,来自packbits doc:“类型为 uint8 的数组,其元素表示对应于输入元素的逻辑(0 或非零)值的位。packed 的形状具有相同的数字尺寸作为输入(除非轴是无,在这种情况下输出是一维)。” - 返回一个 uint8。

标签: python python-3.x numpy bit-manipulation endianness


【解决方案1】:

My first answer 修复了异常。

这个答案,依赖于thisthis

  • 将数组从右侧填充到最接近的 2 次方
  • 重塑有一些数组,每个数组的大小为 32
  • 按数组打包位,然后仅以unit32 的形式查看。
import numpy as np
import math


# https://stackoverflow.com/questions/49791312/numpy-packbits-pack-to-uint16-array
# https://stackoverflow.com/questions/36534035/pad-0s-of-numpy-array-to-nearest-power-of-two/36534077


def next_power_of_2(number):
    # Returns next power of two following 'number'
    return 2**math.ceil(math.log(number, 2))


a = np.array([
    1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1,
    1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1
])

# a = np.array([
#     0 for _ in range(31)
# ] + [1])
padding_size = next_power_of_2(len(a)) - len(a)
b = np.concatenate([a, np.zeros(padding_size)])
c = b.reshape((-1, 32)).astype(np.uint8)
d = np.packbits(c, bitorder='little').view(np.uint32)

print(d)

输出:

[2846675629 160601]

【讨论】:

  • 谢谢,它有效!看来我们不需要填充到 2 的下一个幂,只需填充到 32 位,对吧?
  • @Curious 没错。我想我做得过火了。
【解决方案2】:

您不能像以前那样使用 array.dtype = np.uint32,因为 numpy 数组在内存中必须是连续的。

相反,您可以创建新类型的新数组。

import numpy as np

array = np.array([1,0,1,1,0,1,0,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,1,0,1,1,0,0,1,1,0,1,0,1,1,0,0,1,1,1,0,0,1])
array = np.packbits(array, bitorder='little')
array = np.array(array, dtype=np.uint32)
array.byteswap(inplace=True)

print(array)

【讨论】:

  • 我希望输出数组只包含 2 个值(总共 64 位),因为我有 50 个输入位。但是,您的代码会产生 7 个值:[2902458368 3523215360 2885681152 2835349504 1493172224 1929379840 33554432]
  • 请编辑您的问题。它不能像现在这样重现。
  • 究竟什么是不可重现的?我没明白。你的意思是最初的问题(我可以使用安装了 numpy 的python sample.py 运行它)还是我之前对你的回答的评论?
  • minimal reproducible example 我的意思是:1. 准确的预期输出 2. 完整的错误跟踪 3. 最小 - 你能用比 50 位更容易理解的东西来重现这个吗?
  • 我在问题中添加了预期的输出
猜你喜欢
  • 1970-01-01
  • 2017-01-03
  • 1970-01-01
  • 1970-01-01
  • 2014-05-25
  • 2015-06-07
  • 1970-01-01
  • 2018-05-01
  • 1970-01-01
相关资源
最近更新 更多