我目前正在编写一个需要位操作的python程序。
输入是整数数组的序列,比如说
1, 2, 3, 4, 5, 6, 7, 8
输出是检查每个整数是等于还是大于3.如果是,则为1,否则为0.输出为二进制整数:
00111111
我该怎么做?
如果有新号码,请说出9.我需要删除序列中的第一个数字,比如序列中的1。所以我的新序列将是:
2,3,4,5,6,7,8,9
然后结果应为01111111
。但是我想从我的旧整数00111111
使用左移操作。我怎样才能做到这一点?谢谢!
答案 0 :(得分:3)
您可以使用以下功能:
# Assumes msb first, lsb last, bits is iterable of integers in [0,1]
def bits2int(bits):
v = 0
for b in bits:
v <<= 1
v += b
return v
然后,根据您的输入数组arr
,使用以下命令调用它:
arr = [1, 2, 3, 4, 5, 6, 7, 8]
val = bits2int([i >= 3 for i in arr])
print(val) # 63
print("{:08b}".format(val)) # 00111111
对于您的其他输入数组,您可以使用以下命令调用它:
arr = [2,3,4,5,6,7,8,9]
val = bits2int([i >= 3 for i in arr])
print(val) # 127
print("{:08b}".format(val) # 01111111
修改:从问题的最后部分开始,看起来您希望在给定一些新整数的情况下“更新”val
。
可以使用上述方法(更新arr
,再次在更新的bits2int
上调用arr
)或“手动”,使用以下方法完成:
arr = [1, 2, 3, 4, 5, 6, 7, 8]
val = bits2int([i >= 3 for i in arr])
# Now, val = 63 = 0b00111111
# Handle additional integer
new_int = 9 # Give the additional integer a name, to make it clear
val <<= 1 # Shift up all bits
val |= (new_int >= 3) # Set lowest bit according to some logic
# (here, if new_int >= 3)
print(val)
print("{:08b}".format(val))
最后,val与上面第二个bits2int
调用的输出相同:
127 01111111
请注意,<<=
运算符是就地/扩充的左移运算符,|=
运算符是就地/扩充的按位运算符。
<强>更新强>
根据评论中的讨论,您不仅要跟踪值,还要跟踪位数。这比上面的简单功能更复杂。这是您可以使用的基础课程:
class BitArray(object):
@classmethod
def from_array(cls, bits=None):
self = cls()
if bits is None: bits = []
self.val = 0
for b in bits:
self.val <<= 1
self.val += b
self.nbits = len(bits)
return self
@classmethod
def from_int(cls, val, nbits=None):
self = cls()
if nbits is None: nbits = val.bit_length()
self.val = val
self.nbits = nbits
return self
# Define equality
def __eq__(self, other):
if self.val != other.val: return False
if self.nbits != other.nbits: return False
return True
# Better representation of BitArray object
def __repr__(self):
return "BitArray(nbits=%d, val=%d)" % (self.nbits, self.val)
# Output a binary string of nbits width, or width if specified (width must be >= nbits)
def binstr(self, width=None):
if width is None: width = self.nbits
assert width >= self.nbits
return "{:b}".format(self.val).zfill(width)
# Conversion to int e.g. int(BitArrayInstance)
def __int__(self):
return self.val
# "in-line" left shift
def __ilshift__(self, n):
self.val <<= n
self.nbits += 1
return self
# "in-line" bitwise or
def __ior__(self, v):
self.val |= v
return self
# Helper function to generate a bit mask
def _mask(self):
return (1 << self.nbits) - 1
# Trim n bits off the left side (truncate n most significant bits)
def ltrim(self, n):
self.nbits = max(0, (self.nbits - n))
self.val &= self._mask()
# "Pops" off msb, shifts all bits up 1, sets lsb to v
def rotate_in(self, v):
v = int(v)
assert v in [0,1]
self.ltrim(1)
self.__ilshift__(1)
self.__ior__(v)
return self
现在,在执行相同的<<=
和|=
操作后,您可以使用ltrim
方法删除最左侧的位/ msb:
arr = [1, 2, 3, 4, 5, 6, 7, 8]
b1 = BitArray.from_array([i >= 3 for i in arr])
print(b1)
new_int = 9
b1 <<= 1
b1 |= (new_int >= 3)
b1.ltrim(1)
print(b1)
输出:
BitArray(nbits=8, val=63) BitArray(nbits=8, val=127)
请注意,两个打印功能中的nbits
值相同。 <<= 1
会将nbits
增加1,然后ltrim(1)
会将其减少1,然后返回8.它会像你问的那样“抛弃”最左边的一点。
我还为这3个操作rotate_in(bit_val)
提供了便利功能。您可以通过以下方式使用它:
arr = [1, 2, 3, 4, 5, 6, 7, 8]
b2 = BitArray.from_array([i >= 3 for i in arr])
print(b2)
new_int = 9
b2.rotate_in(new_int >= 3)
print(b2)
此输出(与上述相同):
BitArray(nbits=8, val=63) BitArray(nbits=8, val=127)
我们可以验证这两个BitArray
与
# Ensure b1 equals b2
print(b1 == b2) # True
最后,为了验证这对于长度为600的输入数组也是如此,我们创建一个600个元素的1s列表,将其转换为BitArray
,然后比较结果值(int(BitArrayInstance)
1}})我们期望它:
# Test 600 element array :)
arr = [1] * 600
b3 = BitArray.from_array(arr)
print(int(b3) == ((2**600) - 1)) # True