You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法用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的两个核心规则:

  1. 输入字节的比特反转:KERMIT要求每个输入字节先反转8位再参与计算,而非直接使用原始字节顺序
  2. 最终结果的二次处理:计算完成后需要反转整个16位CRC值,再交换高低字节顺序

这两个步骤是Python实现能得到0xA40E的关键,而多数基础CRC实现会忽略这些细节,导致输出0x76C7这类错误结果。

验证

将你的测试输入传入上述方法,返回的十六进制结果应为0xA40E,与Python实现完全一致。

内容的提问来源于stack exchange,提问作者philbot999

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:17:48