如何在二进制整数中保留前导零(Python)?

2 投票
3 回答
3316 浏览
提问于 2025-04-18 00:30

我需要为一个十六进制的串行单词字符串计算一个校验和,使用的是异或运算。根据我有限的知识,这个操作需要用到位运算符 ^。另外,数据还需要转换成二进制整数的形式。下面是我写的简单代码,但它计算出的校验和是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。

撰写回答