几乎所有教程讲的原理都是把数据看成一串很长的 01 组成的二进制数,计算时按 bit 逐位右移异或多项式,refin=true 时需要把整串数据反转再计算。(这些理解起来不难,并且我也手算了 n 多次都能和计算器结果符合上。)
但是实际实现代码却是按字节计算,refin=false refout=false 时 byte 左移异或多项式,refin=true refout=true 时 byte 右移异或多项式的反转值。
目前仅能勉强理解 refin=false refout=false 的情况,在数据中间插入任意个 0 不影响最后的计算结果,所以每个字节左移补 0 异或多项式不会影响结果。
现在实在无法理解的是 refin=true refout=true 的情况,
以下面代码为例:
/******************************************************************************
* Name: CRC-5/ITU x5+x4+x2+1
* Poly: 0x15
* Init: 0x00
* Refin: True
* Refout: True
* Xorout: 0x00
* Note:
*****************************************************************************/
public static byte crc5_itu(byte[] data,int offset,int length){
byte i;
byte crc = 0; // Initial value
length += offset;
for(int j=offset;j<length;j++) {
crc ^= data[j];
for (i = 0; i < 8; ++i){
if ((crc & 1) == 0)
crc = (byte) ((crc&0xff) >> 1);
else
crc = (byte) (((crc&0xff) >> 1) ^ 0x15);// 0x15 = (reverse 0x15)>>(8-5)
}
}
return (byte) (crc & 0x1f);
}
refin=true refout=true 时为什么反转的是多项式且 CRC 右移?并且最后的结果也不用反转?
这几天看了 n 多文章,代码也敲了 n 多遍,运行的每一步都和手算过程一一对照,也实现了完全按 bit 左移异或的代码(和手算过程完全一致,而非按字节计算的方式),仍然难以理解。
后面还有查表法的原理也看的不明不白,只理解了异或算法遵循结合律所以中间一部分计算过程可以预先计算存表,数据来的时候可以直接查表简化计算过程。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.