我正在编写将整数转换为填充的 8 位字符串的代码。然后我想将这些字符串写入二进制文件。我在确定与当前使用的 numpy 数组一起使用的正确dtype
时遇到问题。
在下面的代码中,当我使用 dtype=np.int8
设置bin_data
变量时,输出为:
$ python bool_dtype.py
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 1, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
[0 0 0 0 1 0 0 0 0]
16
当bin_data
设置为 dtype=np.bool_
时,输出始终为 true,如下所示:
$ python bool_dtype.py
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 1, bool(a[j]) = True
a[j] = 1, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 1, bool(a[j]) = True
a[j] = 1, bool(a[j]) = True
[ True True True True True True True True True]
16
当我在使用dtype=np.int8
时查看数据的 xxd 转储时,我看到一个预期的字节用于表示每个位 (1,0( IE 00000001或 00000000。使用dtype=np.bool_
会导致同样的问题。
所以我的两个主要问题是
为什么布尔值在读取数组元素时总是读取为 True。
当我将数据写入文件时,如何更有效地存储数据,以便单个位不存储为字节,而只是连接到前一个元素?
这是有问题的代码,谢谢!
#!/usr/bin/python2.7
import numpy as np
import os
# x = np.zeros(200,dtype=np.bool_)
# for i in range(0,len(x)):
# if i%2 != 1:
# x[i] = 1
data_size = 2
data = np.random.randint(0,9,data_size)
tx=''
for i in range(0,data_size):
tx += chr(data[i])
data = tx
a = np.zeros(8,dtype=np.int8)
bin_data = np.zeros(len(data)*8,dtype=np.bool_)
# each i is a character byte in data string
for i in range(0,len(data)):
# formats data in 8bit binary without the 0b prefix
a = format(ord(data[i]),'b').zfill(8)
for j in range(0,len(a)):
bin_data[i*len(a) + j] = a[j]
print("a[j] = {}, bool(a[j]) = {}").format(a[j], bool(a[j]))
print bin_data[1:10]
print len(bin_data)
path = os.getcwd()
path = path + '/bool_data.bin'
data_file = open(path, "wb")
data_file.write(bin_data)
data_file.close()
编辑:
我希望在使用dtype=np.bool_
时看到什么
>>> import numpy as np
>>> a = np.zeros(2,dtype=np.bool_)
>>> a
array([False, False], dtype=bool)
>>> a[1] = 1
>>> a
array([False, True], dtype=bool)
- bool 总是返回 true 的原因是 a[j] 是一个非空字符串。在使用 bool 进行测试之前(以及在将其作为 numpy bool 数组的条目之前(,您需要将 a[j] 转换为 int。
- 你可以调用numpy.packbits将布尔数组压缩成uint8数组(如果需要,它会为你填充(,然后调用numpy.unpackbits来反转操作。
编辑:
如果布尔数组的长度不是 8 的倍数,则在打包和解包后,数组将填充为零,以使长度成为 8 的倍数。在这种情况下,您有两种选择:
- 如果可以安全地截断数据以具有可被 8 整除的位数,请执行此操作。像这样:
data=data[:8*(len(data)/8)]
- 如果您负担不起截断,那么您将以某种方式记录有意义的位数。我建议使打包数据的第一个字节等于有意义的位数 mod 8。这只会增加一个字节的内存开销,并且不会增加太多的计算时间。像这样:
包装
bool_data = np.array([True, True, True])
nbits = len(bool_data)
rem = nbits % 8
nbytes = nbits/8
if rem: nbytes += 1
data = np.empty(1+nbytes, dtype=np.uint8)
data[0] = rem
data[1:] = np.packbits(bool_data)
打开
rem = data[0]
bool_data = np.unpackbits(data[1:])
if rem:
bool_data = bool_data[:-(8-rem)]