无法用C#复现CRC-16/CCITT KERMIT正确计算结果求助
修复CRC-16/CCITT KERMIT的C#实现以匹配Python结果
CRC-16/KERMIT的结果差异通常出现在容易忽略的比特/字节反转规则上,而非多项式或初始值。以下是修正后的C#实现,以及差异原因分析:
正确的C#实现
public static ushort ComputeCrc16Kermit(byte[] inputData) { ushort crcRegister = 0x0000; // 初始值 const ushort Polynomial = 0x1021; foreach (byte rawByte in inputData) { // 预处理:反转当前字节的8位比特(KERMIT强制要求) byte reversedByte = ReverseSingleByte(rawByte); crcRegister ^= (ushort)(reversedByte << 8); // 逐位计算CRC for (int bit = 0; bit < 8; bit++) { crcRegister = (ushort)((crcRegister & 0x8000) != 0 ? ((crcRegister << 1) ^ Polynomial) : (crcRegister << 1)); } } // 后处理:反转整个16位CRC结果,再交换高低字节 crcRegister = Reverse16Bits(crcRegister); crcRegister = (ushort)(((crcRegister & 0xFF00) >> 8) | ((crcRegister & 0x00FF) << 8)); return crcRegister; } // 辅助方法:反转单个字节的8位比特 private static byte ReverseSingleByte(byte b) { return (byte)(((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16); } // 辅助方法:反转16位整数的所有比特 private static ushort Reverse16Bits(ushort value) { value = (ushort)(((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1)); value = (ushort)(((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2)); value = (ushort)(((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4)); value = (ushort)((value >> 8) | (value << 8)); return value; }
差异原因分析
你的原有C#代码大概率漏掉了KERMIT CRC的两个核心规则:
- 输入字节的比特反转:KERMIT要求每个输入字节先反转8位再参与计算,而非直接使用原始字节顺序
- 最终结果的二次处理:计算完成后需要反转整个16位CRC值,再交换高低字节顺序
这两个步骤是Python实现能得到0xA40E的关键,而多数基础CRC实现会忽略这些细节,导致输出0x76C7这类错误结果。
验证
将你的测试输入传入上述方法,返回的十六进制结果应为0xA40E,与Python实现完全一致。
内容的提问来源于stack exchange,提问作者philbot999
相关产品推荐
相关产品推荐

