python - 在python中使用numpy解包和打包除无符号整数以外的位?
问题描述
我正在尝试使用 python 中的 NumPy 包使用numpy.unpackbits()
和函数来打包和解包位。numpy.unpackbits()
以下是这些功能正常工作的方式。
import numpy as np
x = np.unpackbits(np.array(1, dtype='uint8')) # [0 0 0 0 0 0 0 1]
np.packbits(x) # [1]
x = np.unpackbits(np.array(100, dtype='uint8')) # [0 1 1 0 0 1 0 0]
np.packbits(x) # [100]
x = (np.unpackbits(np.array(255, dtype='uint8'))) # [1 1 1 1 1 1 1 1]
np.packbits(x) # [255]
但是,这不适用于大于 255 的值,因为不支持无符号整数。
x = (np.unpackbits(np.array(300, dtype='uint16')))
# TypeError: Expected an input array of unsigned byte data type
我试图让这些解决方案发挥作用,但它们不会产生像上面那样连贯的输出。我也不知道如何“打包”它们。
def unpackbits(x, num_bits):
if np.issubdtype(x.dtype, np.floating):
raise ValueError("numpy data type needs to be int-like")
xshape = list(x.shape)
x = x.reshape([-1, 1])
mask = 2**np.arange(num_bits, dtype=x.dtype).reshape([1, num_bits])
return (x & mask).astype(bool).astype(int).reshape(xshape + [num_bits])
结果如下。
unpackbits(np.array(1, dtype='uint8'), 16) # [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
# Starts from the right? Why? Should it not be [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]?
unpackbits(np.array(100, dtype='uint8'), 16) # [0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0]
# Not what I would expect.
unpackbits(np.array(255, dtype='uint8'), 16) # [1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0]
# Should be [0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1].
unpackbits(np.array(300, dtype='uint8'), 16) # [0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0]
# Is 13,312 according the caluclator provided in Windows 10 20H2 quite a way off from 300.
unpackbits(np.array(300, dtype='uint16'), 16) # [0 0 1 1 0 1 0 0 1 0 0 0 0 0 0 0]
# Now the calculator says the decimal equivalent is 13,440 after changing to 'uint16'.
np.unpackbits(np.array([1], dtype='uint16').view('uint8')) # [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]
# Not what I expected but...
np.unpackbits(np.array([1], dtype='uint8').view('uint8')) # [0 0 0 0 0 0 0 1]
# ...works as expected with 'uint8'. Why does it behave in such a way?
np.unpackbits(np.array([100], dtype='uint16').view('uint8')) # [0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0]
np.unpackbits(np.array([100], dtype='uint8').view('uint8')) # [0 1 1 0 0 1 0 0]
# The same pattern...
np.unpackbits(np.array([255], dtype='uint16').view('uint8')) # [1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0]
np.unpackbits(np.array([255], dtype='uint8').view('uint8')) # [1 1 1 1 1 1 1 1]
# ...continues
np.unpackbits(np.array([300], dtype='uint16').view('uint8')) # [0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1] 11,265 according to the calculator.
第三种解决方案:在此处输入链接描述
def unpackbits_2(in_intAr,Nbits):
''' convert (numpyarray of uint => array of Nbits bits) for many bits in parallel'''
inSize_T= in_intAr.shape
in_intAr_flat=in_intAr.flatten()
out_NbitAr= np.zeros((len(in_intAr_flat),Nbits))
for iBits in range(Nbits):
out_NbitAr[:,iBits]= (in_intAr_flat>>iBits)&1
out_NbitAr= out_NbitAr.reshape(inSize_T+(Nbits,))
return out_NbitAr
我已经修改了原始版本以使用 Python 3,结果如下。
unpackbits_2(np.array(1, dtype='uint16'),16) # [1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
# What's with the dots? The numbers are still not right.
unpackbits_2(np.array(100, dtype='uint16'),16) # [0. 0. 1. 0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
# The binary is 9,728 (excluding the dots) according to the calculator.
unpackbits_2(np.array(255, dtype='uint16'),16) # [1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
unpackbits_2(np.array(300, dtype='uint16'),16) # [0. 0. 1. 1. 0. 1. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
# Converting the binary results in 13,440 in base 10.
我也尝试过使用struck.unpack()
但无济于事。
对于多种数据类型(uint8、uint16、uint32、uint64、uint128 等),一种将 int 转换为二进制并返回的高性能(因为此操作将执行数百万次)pythonic 方式将不胜感激。例如 uint8: 255 -> [1 1 1 1 1 1 1 1] -> 255
; uint16: 255 -> [0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1] -> 255
; 等等。
可以为浮点数和字符执行此操作,还是它们不是正确的数据类型?
解决方案
推荐阅读
- javascript - React hooks 不能在 JSX 中映射数组
- laravel - Laravel Eloquent ORM 查询不工作 Laravel v6.9
- javascript - 从服务工作者缓存中删除特定文件?
- python - Python:代码中未提及的变量被覆盖。为什么?
- mongodb - Mongodump 无法指定用户名和 uri
- python - '_io.TextIOWrapper' 对象在 python3 中不是可下标的错误
- java - CometD 和 Kafka 消费者
- amazon-ecs - Quarkus 启动警告
- flutter - 如何在颤动中获取特定小部件的结构?
- python - Pandas DataFrame.to_csv() OSError: [Errno 22] Invalid argument and PermissionError: [Errno 13] Permission denied