用python內建的binascii模組計算字串的校正碼,出來的是負值,與用c寫的程式得出的校正碼不一樣,所以就研究了一下。發現別人用的python3.0版本binascii模組計算出的crc32校正碼是我想要的,沒辦法只好自己用python實現一下crc32的演算法了。發現演算法很簡單,就是某些實現裡面弄了好幾個函數倒搞複雜了,其實按核心演算法演算法走一邊很容易就理解和應用了。
因為直接從c程式轉過來的,結果發現python2.5(我用的版本ActivePython 2.5.2.2 (ActiveState Software Inc.) based on
Python 2.5.2 (r252:60911, Mar 27 2008, 17:57:18) [MSC v.1310 32 bit (Intel)] on win32)裡面的按位取反盡然不是按位取反,網上搜出好多文章都說~在python中是按位取反,自己測試了下:
>>> ~3,~2,~1,~0,~-1,~-2,~3
(-4, -3, -2, -1, 0, 1, -4)
才恍然大悟,原來是這裡出錯了。
再看:
>>> import binascii
>>> binascii.crc32("我們")
-603163415
如果把下面代碼的倒數第二行
dwCrc32 = dwCrc32 ^ 0xFFFFFFFFL
改成
dwCrc32 = ~dwCrc32
然後運行:mycrc32("我們") 得到結果也是-603163415
所以懷疑python2.5裡面是不是也中了這個陷阱了。
用下面的代碼得到的就和c代碼計算得到的crc32校正碼一致了。不過python支援的正數要比c的大,所以按位求反這裡只能保證32位情況下得到和c代碼一樣的校正碼。
#coding=gbk
def mycrc32(szString):
m_pdwCrc32Table = [0 for x in range(0,256)]
dwPolynomial = 0xEDB88320;
dwCrc = 0
for i in range(0,255):
dwCrc = i
for j in [8,7,6,5,4,3,2,1]:
if dwCrc & 1:
dwCrc = (dwCrc >> 1) ^ dwPolynomial
else:
dwCrc >>= 1
m_pdwCrc32Table[i] = dwCrc
dwCrc32 = 0xFFFFFFFFL
for i in szString:
b = ord(i)
dwCrc32 = ((dwCrc32) >> 8) ^ m_pdwCrc32Table[(b) ^ ((dwCrc32) & 0x000000FF)]
dwCrc32 = dwCrc32 ^ 0xFFFFFFFFL
return dwCrc32