用python实现crc32求字符串校验码

用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

 

点赞