如何将CRC16ccITT算法的C++代码转换为Python代码?

2024-04-19 00:14:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个C++编写的CRC16-ccITT算法的示例代码,我需要帮助将它转换成Python。在

C++代码:

#include<iostream>

using namespace std;

unsigned short calculateCRC(unsigned char data[], unsigned int length)
{
        unsigned int i;
        unsigned short crc = 0;

        for(i=0; i<length; i++){
                crc = (unsigned char)(crc >>8) | (crc<<8);
                crc ^= data[i];
                crc ^= (unsigned char)(crc & 0xff) >> 4;
                crc ^= crc << 12;
                crc ^= (crc & 0x00ff) << 5;
        }

        return crc;
}

int main()
{
        unsigned int length;
        length = 15;

        unsigned char data[length] = {0x01,0x08,0x00,0x93,0x50,0x2e,0x42,0x83,0x3e,0xf1,0x3f,0x48,0xb5,0x04,0xbb};
        unsigned int crc;
        crc =  calculateCRC(data, length);
        cout<< std::hex << crc << '\n';
}

此代码给出9288作为正确的输出。在

我在Python中尝试了以下方法:

^{pr2}$

输出0xf988334b0799be2081。在

你能帮我明白我做错了什么吗? 非常感谢。在


Tags: 代码算法示例dataincludelengthintcrc
1条回答
网友
1楼 · 发布于 2024-04-19 00:14:37

Python的{{CD1>}类型是无界的,但是C/C++ ^ {CD2>}值在2字节中表示,当向左移动时,溢出。您需要在Python中添加masking以达到相同的效果,即删除任何高于第16个最高有效位的位。这只需要在值向左移动时才需要,因为右移已经删除了最右旋转的位。在

接下来,您将把^{} and ^{} bitwise operators^{} and ^{} boolean logical operators混淆。C++代码使用位运算符,在Python中使用相同的运算符。在

最后但并非最不重要的是,将转换为十六进制留给调用者,不要在CRC函数本身中这样做:

UNSIGNED_SHORT_MASK = 0xFFFF  # 2 bytes, 16 bits.

def calculateCRC(data):
    crc = 0
    for dat in data:
        crc = (crc >> 8) | (crc << 8 & UNSIGNED_SHORT_MASK)
        crc ^= dat
        crc ^= (crc & 0xff) >> 4
        crc ^= crc << 12 & UNSIGNED_SHORT_MASK
        crc ^= (crc & 0x00ff) << 5
    return crc

现在您可以得到相同的输出:

^{pr2}$

我使用^{} function而不是hex()来创建没有0x前缀的十六进制输出。在

A^ {A5}正确地指出,我们不需要为每个左移位操作掩盖;因为C/C++操作自然会产生掩蔽值,这并不意味着我们需要像这里经常这样做。每次迭代屏蔽一次就足够了:

def calculateCRC(data):
    crc = 0
    for dat in data:
        crc = (crc >> 8) | (crc << 8)
        crc ^= dat
        crc ^= (crc & 0xFF) >> 4
        crc ^= crc << 12
        crc ^= (crc & 0x00FF) << 5
        crc &= 0xFFFF
    return crc

我们可能有更多的捷径可以应用于剃毛操作,从而加快操作速度,但如果速度真的是个问题,无论如何,我会在Cython或C或其他本机编译的选项中重新实现它。在

另请注意,您可以使用bytes对象,而不必使用整数列表:

data = b'\x01\x08\x00\x93\x50\x2e\x42\x83\x3e\xf1\x3f\x48\xb5\x04\xbb'

循环在^ {< CD10>}对象上仍然给您0到255的整数,就像C++中的^ {CD12>}数组一样。在

最后,您实际上不必自己翻译代码,您可以使用现有的项目,如^{},它实现了这个特定的CRC16变体以及其他许多变体:

>>> from crccheck.crc import CrcXmodem
>>> print(format(CrcXmodem.calc(data), '04x'))
9288

crccheck是用纯Python编写的。对于本机实现,有^{}。这个库的文档有点欠缺,但它也非常灵活和强大,实际上包括预定义的函数:

>>> from crcmod.predefined import mkPredefinedCrcFun
>>> xmodem = mkPredefinedCrcFun('xmodem')
>>> print(format(xmodem(data), '04x'))
9288

相关问题 更多 >