1. 程式人生 > >python 計算校驗和

python 計算校驗和

校驗和是經常使用的,這裡簡單的列了一個針對按位元組計算累加和的程式碼片段。其實,這種累加和的計算,將位元組翻譯為無符號整數和帶符號整數,結果是一樣的。

使用python計算校驗和時記住做截斷就可以了。 這裡僅僅是作為一個程式碼樣本,權作標記,直接上程式碼

'''
Created on 2014年9月4日

@author: lenovo
'''
import random

'''
實際計算校驗和時,解釋為無符號整數還是帶符號整數,結果必然是一樣的。因為基於補碼方式儲存,計算加法時都是按位加,然後該進位的就進位。
只是最終的結果,如果是帶符號整數,最高位會被解釋符號位
'''

def char_checksum(data, byteorder='little'):
    '''
    char_checksum 按位元組計算校驗和。每個位元組被翻譯為帶符號整數
    @param data: 位元組串
    @param byteorder: 大/小端
    '''
    length = len(data)
    checksum = 0
    for i in range(0, length):
        x = int.from_bytes(data[i:i+1], byteorder, signed=True)
        if x>0 and checksum >0:
            checksum += x
            if checksum > 0x7F: # 上溢位
                checksum = (checksum&0x7F) - 0x80 # 取補碼就是對應的負數值
        elif x<0 and checksum <0:
            checksum += x
            if checksum < -0x80: # 下溢位
                checksum &= 0x7F
        else:
            checksum +=x # 正負相加,不會溢位
        #print(checksum)    
    
    return checksum
    

def uchar_checksum(data, byteorder='little'):
    '''
    char_checksum 按位元組計算校驗和。每個位元組被翻譯為無符號整數
    @param data: 位元組串
    @param byteorder: 大/小端
    '''
    length = len(data)
    checksum = 0
    for i in range(0, length):
        checksum += int.from_bytes(data[i:i+1], byteorder, signed=False)
        checksum &= 0xFF # 強制截斷
        
    return checksum

簡單說明一下上面的指令碼。如果是當作無符號整數來計算,則演算法要簡單很多,實際上都可以縮減為一句程式碼的事。如果是當作帶符號整數來計算,則演算法要複雜一下,要處理各種上溢位和下溢位的情形。正如文章開頭指出的,不論使用哪種方式,最後的二進位制表示都是一樣的。所以一般情況下可以使用無符號整數來計算校驗和,簡單快速。

下面是驗證使用的例子,

data1=bytes(b'\x01\x7F\xFF')
    data2=bytes([random.randrange(0,256) for i in range(0, 10000)])
    assert(uchar_checksum(data1) == 127)
    assert(char_checksum(data1) == 127)
    assert((uchar_checksum(data2)&0xFF) == (char_checksum(data2)&0xFF))
    print('OK')

上面的演算法也很容易推廣到兩個位元組或者四個位元組的校驗和計算

over