Java实现CRC-16/EN-13757与在线计算器结果不符问题排查
问题排查与修复方案
你的代码和在线计算器结果不一致的核心原因是忽略了CRC-16/EN-13757的输入位反转(RefIn=True)和输出位反转(RefOut=True)参数,这两个是该CRC变种的必填规则,同时需要确保最终结果异或0xFFFF。
CRC-16/EN-13757的标准参数
- 多项式:
0x3D65(与你的定义一致) - 初始值:
0x0000(与你的定义一致) - 输入反转:每个字节的8位顺序反转(RefIn=True)
- 输出反转:计算得到的16位CRC整体反转(RefOut=True)
- 输出异或:
0xFFFF(与你的定义一致)
修复后的代码
添加字节反转和16位反转的辅助函数,修改计算逻辑以符合参数要求:
public class crcTest { private static final int INITIAL_VALUE = 0x0000; private static final int POLYNOMIAL = 0x3D65; private static final int XOR_OUT = 0xFFFF; // 反转单个字节的8位 private static byte reverseByte(byte b) { int reversed = 0; for (int i = 0; i < 8; i++) { reversed = (reversed << 1) | (b & 1); b >>= 1; } return (byte) reversed; } // 反转16位CRC值 private static int reverse16(int crc) { int reversed = 0; for (int i = 0; i < 16; i++) { reversed = (reversed << 1) | (crc & 1); crc >>= 1; } return reversed & 0xFFFF; } public static byte[] calc(byte[] data) { int crc = INITIAL_VALUE; for (byte b : data) { // 先反转输入字节,符合RefIn=True要求 byte reversedByte = reverseByte(b); crc = crc ^ (reversedByte & 0xFF); for (int i = 0; i < 8; i++) { if ((crc & 0x0001) != 0) { crc = (crc >>> 1) ^ POLYNOMIAL; } else { crc >>>= 1; } } } // 先反转CRC结果,再异或输出值,符合RefOut=True和XOR_OUT要求 crc = reverse16(crc) ^ XOR_OUT; return new byte[]{(byte) ((crc >> 8) & 0xff), (byte) (crc & 0xff)}; } public static void main(String[] args) { byte[] data = {0x40, 0x31, 0x26, 0x21, 0x5e, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x22}; byte[] crcBytes = calc(data); for (byte b : crcBytes) { System.out.printf("%02X ", b); } } }
验证结果
运行上述代码,输出为5E 87,与预期结果一致。
错误点分析
- 输入未反转:原代码直接使用原始字节计算,而EN-13757要求每个字节的位顺序反转后再参与运算。
- 输出未反转:计算完成后未将16位CRC整体反转,直接异或输出值,不符合算法规则。
内容的提问来源于stack exchange,提问作者CodeNotFound
相关产品推荐
相关产品推荐

