2014-03-30 2 views
2

XOR을 사용하여 16 진수 직렬 문자열에 대한 체크섬을 계산해야합니다. 내 (제한적) 지식을 위해서는 비트 연산자 ^를 사용하여 수행해야합니다. 또한 데이터는 이진 정수 형식으로 변환되어야합니다. 아래는 나의 초보적인 코드입니다. 그러나 계산 된 체크섬은 1000831입니다. 그것은 01001110 또는 47hex 여야합니다. 나는 오류가 선행 0이 누락 된 것일 수 있다고 생각합니다. 앞에 오는 0을 추가하려고 시도한 모든 형식화는 이진 정수를 문자열로 되돌립니다. 나는 어떤 제안을 주셔서 감사합니다.선행 0을 이진 정수 (파이썬)로 유지하는 방법은 무엇입니까?

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)의 행동입니다. doc here을 참조하십시오. 그래서 파이썬 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

OP로 사용하는 것으로 의심되는 python3에서 실패 할 것입니다. 왜냐하면 그는 print로 함수를 사용하기 때문입니다. – Hyperboreus

+0

@Hyperboreus : 가능하지만 태그가 2.7입니다. – DSM

+0

@DSM 나는 그 주석을 쓸 때 특정 버전에 대한 태그가 지정되지 않았다고 맹세 할 수있다. 나는 장님 이었음에 틀림 없다. – Hyperboreus

관련 문제