CRC校验算法学习

原文:http://www.repairfaq.org/filipg/LINK/F_crc_v31.html

本文根据上述链接原文翻译而来,如有错误,忘广大网友互相帮忙纠正,谢谢!

1、前言:

1.0 作者

1.1 代码示例

crcmodel.h 
crctable.c
crcmodel.c

 

1.2 摘要

2、简介:错误校验

错误校验的目的是通过检验传输信号中的噪音干扰(出错的源头),以检验传输数据是否出错。

为此,从有效的数据构建一个校验值(称之为校验和),包含在传输数据流中,作为检验数据是否完备。

接收方使用同样的计算方法对信息数据进行求校验值,和数据中的校验值比较,以确定数据是否正确无误。

例如,我们通过将信息数据采用和校验方法(33 =(6+23+4)%256),对下列数据进行校验 :

  原始信息数据:6, 23, 4

  带校验和的数据:6, 23, 4, 33

  实际接收的数据:6, 27, 4, 33

我们将接收的数据 { 6, 27, 4 } 进行和校验((6+27+4)%256 = 37),结果与接收的校验码 33 进行比较,校验码不一致,说明接收的数据出错已经损坏。

还有一种更危险的情况就是,当信息数据和校验数据同时被损坏,而导致校验一致的情况。这种情况不可避免,最有效的办法就是增加校验和中的信息量(例如将一个字节校验增加到两个),来减小这种情况发生的概率。

存在其它的错误校验计时,这些技术对信息数据进行比较复杂的转换,从而注入更多的冗余信息,

本文仅仅介绍 CRC 校验算法,它属于错误校验算法的一种类型。

CRC校验通过在数据末尾附加校验码的形式保证数据的完整性。

3.复杂性的需要

在上一节和校验示例中,我们通过和校验的方法检测数据损坏,通过求和再求模256的形式求得校验码。

  原始信息数据:6, 23, 4

  带校验和的数据:6, 23, 4, 33

  实际接收的数据:6, 27, 4, 33

和校验的的这种方法太过于简单,如果信号数据出错,我们仍然有1/256概率检测不到错误,例如:

  原始信息数据:6, 23, 4

  带校验和的数据:6, 23, 4, 33

  实际接收的数据:8, 20, 5, 33

为了加强校验和,我们把校验码从一个8bit寄存器扩展到16bit寄存器(即 65536,而非 mod 256),从而明显将出错概率由 1/256 降低至 1/65536。

扩充校验码位数虽然这是个好办法,单这种方法是比较失败的,因为所使用的计算方法不够“随机”。

简单的求和校验方法,使得每个字节的数据都可以影响到校验码对应字节的结果,与扩充校验码数据位数无关。 

只有使用更加复杂算法替换简单求和算法,才能减小每个信息数据对校验码的影响,才能解决这个问题。

总结下,我们看到需要下面两个方面才能形成比较强的校验函数:

  数据宽度:宽的数据宽度可以保证更低的出错概率,例如32bit数据给出 1/2^32 的出错概率机会。

  混乱随机:使得每个输入字节具备改变校验码寄存器任意位数的可能性。 

注意:术语 "checksum" ,即校验和,早期用来描述邱丹求和公式,单现在包含更广泛含义,包含更复杂的算法,如 CRC算法 。

4. CRC 算法的基本思想

构建复杂的校验码计算方法有很多种方式。

我们看到使用加法的“校验和”算法不够强大,无法形成有效的校验码。

但研究结果表明使用除法可以,要使用和校验码寄存器一样宽的大除数就可以。

CRC算法的基本思想是把 信息数据当做一个很大的二进制数来处理,用它除以一个固定的二进制数,并将这个除法的余数作为校验码。

接收到信息数据后,接收方执行相同的除法,并将 余数 与 校验码 进行比较来验证信息数据是否完整。

例如:

假定信息数据包含2个字节{ 6, 23 } , 则可以认为是二进制数 0000-0110-0001-0111。

假设使用1个字节校验宽度,使用常数除数位 1001,则校验码为的余数 0000-0110-0001-0111 除以1001。

我们用所学过的除法就可以求得余数。计算过程如下

          ...0000010101101 = 00AD =  173 = 商
         ____-___-___-___-
9= 1001 ) 0000011000010111 = 0617 = 1559 = 除数
被除数   0000.,,....,.,,,
          ----.,,....,.,,,
           0000,,....,.,,,
           0000,,....,.,,,
           ----,,....,.,,,
            0001,....,.,,,
            0000,....,.,,,
            ----,....,.,,,
             0011....,.,,,
             0000....,.,,,
             ----....,.,,,
              0110...,.,,,
              0000...,.,,,
              ----...,.,,,
               1100..,.,,,
               1001..,.,,,
               ====..,.,,,
                0110.,.,,,
                0000.,.,,,
                ----.,.,,,
                 1100,.,,,
                 1001,.,,,
                 ====,.,,,
                  0111.,,,
                  0000.,,,
                  ----.,,,
                   1110,,,
                   1001,,,
                   ====,,,
                    1011,,
                    1001,,
                    ====,,
                     0101,
                     0000,
                     ----
                      1011
                      1001
                      ====
                      0010 = 02 = 2 = 余数

十进制中,1559 除以 9 等于 173 余 2

虽然在信息数据中,每一位的变化对商的影响微乎其微,但对余数的变化确实显而易见的。

5. 多项式算法

上一节介绍的类似 信息数据除以大除数得余数的方法,我们称之为 CRC算法思想。

CRC算法在计算机中实现实际上更加神秘,我们需要用一些更抽象的数学符号来理解它。

在处理CRC算法时候,我们常听到“多项式”一词。一个给定的CRC算法将使用一个特定的"多项式"。

一般来说,CRC算法是用“多项式”运算来操作的,除数、被除数、商、余数,它们都可以被看做具有二元系数的多项式。。

这是什么意思,怎么理解???

被处理的每个数据都可以看做一个字符串,它对应的每个位作为多项式系数。

例如数字 23(十进制),可以看做 17(十六进制)和 10111(二进制)

10111 ,它对应于多项式:  1*x^4 + 0*x^3 + 1*x^2 + 1*x^1 + 1*x^0

化简成更简单的形式为:  x^4 + x^2 + x^1 + x^0

利用这样抽象的方法,我们可以把要处理的 信息数据,除数 都看出是多项式。我们所做的算法和上面一样,只是里面多了很多 x 。

假设我们想 1011 乘以 1101,我们用多项式的表示方法可以表示为

  ( x^3 + x^1 + x^0 )*( x^3 + x^2 + x^0 )

  =(x^6 + x^4 + x^3+ x^5 + x^3 + x^2+ x^3 + x^1 + x^0)

  = x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0

计算到此时候,为了化简得到最简,我们必须要假定 x = 2,来化简 3*x^3 得到结果:

  x^7 + x^3 + x^2 + x^1 + x^0

As Knuth [Knuth81] says (p.400):

"The reader should note the similarity between polynomial arithmetic and multiple-precision arithmetic (Section 4.3.1), where the radix b is substituted for x. The chief difference is that the coefficient u_k of x^k in polynomial arithmetic bears little or no relation to its neighboring coefficients x^{k-1} [and x^{k+1}], so the idea of "carrying" from one place to another is absent. In fact polynomial arithmetic modulo b is essentially identical to multiple precision arithmetic with radix b, except that all carries are suppressed."

Thus polynomical arithmetic mod 2 is just binary arithmetic mod 2 with no carries. While polynomials provide useful mathematical machinery in more analytical approaches to CRC and error-correction algorithms, for the purposes of exposition they provide no extra insight and some encumbrance and have been discarded in the remainder of this document in favour of direct manipulation of the arithmetical system with which they are isomorphic: binary arithmetic with no carry.

能力水平有限,最后这么一大段木有翻译 !_! , Help!

原文地址:https://www.cnblogs.com/aiyauto/p/7141290.html