如何在二进制整数中保留前导零(Python)?
我需要为一个十六进制的串行单词字符串计算一个校验和,使用的是异或运算。根据我有限的知识,这个操作需要用到位运算符 ^。另外,数据还需要转换成二进制整数的形式。下面是我写的简单代码,但它计算出的校验和是1000831,而我希望得到的是01001110或者47的十六进制表示。我觉得问题可能出在缺少前导零上。我尝试过的所有格式化方法都把二进制整数变回了字符串。非常感谢任何建议。
word = ('010900004f')
#divide word into 5 separate bytes
wd1 = word[0:2]
wd2 = word[2:4]
wd3 = word[4:6]
wd4 = word[6:8]
wd5 = word[8:10]
#this converts a hex string to a binary string
wd1bs = bin(int(wd1, 16))[2:]
wd2bs = bin(int(wd2, 16))[2:]
wd3bs = bin(int(wd3, 16))[2:]
wd4bs = bin(int(wd4, 16))[2:]
#this converts binary string to binary integer
wd1i = int(wd1bs)
wd2i = int(wd2bs)
wd3i = int(wd3bs)
wd4i = int(wd4bs)
wd5i = int(wd5bs)
#now that I have binary integers, I can use the XOR bitwise operator to cal cksum
checksum = (wd1i ^ wd2i ^ wd3i ^ wd4i ^ wd5i)
#I should get 47 hex as the checksum
print (checksum, type(checksum))
3 个回答
1
在编程中,有时候我们会遇到一些问题,比如代码运行不正常或者出现错误。这种情况下,我们需要去查找问题的原因。通常,我们可以通过查看错误信息来找到线索。错误信息就像是程序在告诉我们哪里出了问题。
另外,很多时候我们可以在网上找到其他人遇到类似问题的解决方案,比如在StackOverflow这样的论坛上。这里有很多开发者分享他们的经验和解决方法,帮助我们更快地解决问题。
总之,当你遇到困难时,不要害怕去寻找帮助,利用好网络资源,通常能找到解决方案。
s = '010900004f'
b = int(s, 16)
print reduce(lambda x, y: x ^ y, ((b>> 8*i)&0xff for i in range(0, len(s)/2)), 0)
1
只需要这样修改。
之前:
wd1i = int(wd1bs)
wd2i = int(wd2bs)
wd3i = int(wd3bs)
wd4i = int(wd4bs)
wd5i = int(wd5bs)
之后:
wd1i = int(wd1bs, 2)
wd2i = int(wd2bs, 2)
wd3i = int(wd3bs, 2)
wd4i = int(wd4bs, 2)
wd5i = int(wd5bs, 2)
为什么你的代码不工作?
因为你对 int(wd1bs)
的用法理解错了。你可以在 这里查看相关文档。Python 的 int
函数默认是把 wd1bs
当作10进制来处理的。
但是你希望 int
函数把它当作2进制来处理。所以你需要写成 int(wd1bs, 2)
。
或者你也可以像这样重写整个代码。这样你就不需要在这个情况下使用 bin
函数了。这段代码基本上和 @Hyperboreus 的回答是一样的。:)
w = int('010900004f', 16)
w1 = (0xff00000000 & w) >> 4*8
w2 = (0x00ff000000 & w) >> 3*8
w3 = (0x0000ff0000 & w) >> 2*8
w4 = (0x000000ff00 & w) >> 1*8
w5 = (0x00000000ff & w)
checksum = w1 ^ w2 ^ w3 ^ w4 ^ w5
print hex(checksum)
#'0x47'
还有一个更简短的版本。
import binascii
word = '010900004f'
print hex(reduce(lambda a, b: a ^ b, (ord(i) for i in binascii.unhexlify(word))))
#0x47
5
为什么要使用这些转换和昂贵的字符串函数呢?
(我将回答你提问中的X部分,而不是Y部分。)
def checksum (s):
v = int (s, 16)
checksum = 0
while v:
checksum ^= v & 0xff
v >>= 8
return checksum
cs = checksum ('010900004f')
print (cs, bin (cs), hex (cs) )
结果是0x47,正如预期的那样。顺便提一下,0x47是二进制的0b1000111,而不是你所说的0b1001110。