我需要使用XOR计算十六进制串行字符串的校验和。对于我的(有限的)知识,这必须使用按位运算符^来执行。此外,数据必须转换为二进制整数形式。下面是我的基本代码 - 但它计算的校验和是1000831.它应该是01001110或47hex。我认为错误可能是由于错过了前导零。我试图添加前导零的所有格式都将二进制整数转换回字符串。我很感激任何建议。
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))
答案 0 :(得分:5)
为什么要使用所有这些转换和昂贵的字符串函数?
(我会回答你XY-Problem的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所述。
答案 1 :(得分: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)
行为。
请参阅文档here。所以Python int
函数expect wd1bs
默认为10 base。
但是你希望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
答案 2 :(得分:1)
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)