2014-03-30 69 views
2

我需要使用XOR來計算十六進制串行字符串的校驗和。對於我的(有限的)知識,必須使用按位運算符^來執行。此外,數據必須轉換爲二進制整數形式。以下是我的基本代碼 - 但它計算的校驗和是1000831.它應該是01001110或47hex。我認爲這個錯誤可能是由於錯過了前導零。我試圖添加前導零的所有格式都將二進制整數轉換回字符串。我很欣賞任何建議。如何保持二進制整數(python)中的前導零?

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

我想這之前已經得到解決[見這個問題(http://stackoverflow.com/questions/16926130/python-convert-to-binary-and-keep-leading-zeros) – PyNEwbie

+0

0x47!= 0b1001110。很少有奇數以二進制表示的'0'結尾。 – Hyperboreus

+0

@PyNEwbie確實如此,但在這裏我們正面臨一個傑出的XY問題。 – Hyperboreus

回答

5

爲什麼要使用所有這些轉換和昂貴的字符串函數?

(我會回答你XY-Problem,而不是在Y部分的X部分)。

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預期。 Btw 0x47是0b1000111而不是0b1001110。

+0

這是一個非常巧妙的掩蓋然後轉移! +1 – Victory

+0

謝謝 - 這是雄辯的。它確實解決了X部分,使Y部分變得多餘。多餘而神祕。 。 。 – user3284986

+0

@ user3284986很高興提供幫助。不是那麼神祕,只需查看PyNewbie在他對你的問題的評論中發佈的鏈接。 – Hyperboreus

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功能預期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 
+0

你所有的行'wx =(0x ....'都可以寫成wX =(w >> Y * 8)&0xff',先移位然後掩碼,然後總是'0xff' – Hyperboreus

+0

@ Hyperboreus:啊,這是更聰明的方式,謝謝。我的代碼總是非常冗長...... :) –

+0

@ user3284986:我加了解釋看看你的代碼有什麼問題。 –

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) 
+0

在python3中,我懷疑OP會使用它,因爲他使用'print'作爲函數。 – Hyperboreus

+0

@Hyperboreus:可能,但它的標籤爲2.7。 – DSM

+0

@DSM當我發表評論時,我可以發誓它沒有被標記爲任何特定版本。我一定是失明的。 – Hyperboreus