A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHM

http://www.repairfaq.org/filipg/LINK/F_crc_v31.html#CRCV_001


A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHM

 Author : Ross N. Williams


1.前言(略)

"Everything you wanted to know about CRC algorithms, but were afraid to ask for fear that errors in your understanding might be detected."

2.介绍: 错误检测

  The aim of an error detection technique is to enable the receiver of a message transmitted through a noisy (error-introducing) channel to determine whether the message has been corrupted. To do this, the transmitter constructs a value (called a checksum) that is a function of the message, and appends it to the message. The receiver can then use the same function to calculate the checksum of the received message and compare it with the appended checksum to see if the message was correctly received. For example, if we chose a checksum function which was simply the sum of the bytes in the message mod 256 (i.e. modulo 256), then it might go something as follows. All numbers are in decimal.

    错误检测的目的是让信息的接收者能够判别从有噪声的信道传来的信息是否被干扰。为了达到这样的目的,发送者使用某个以消息为参数的函数式构造出一个值(校验和),并将该值附加在信息的后面。接收者使用相同的函数计算出接收到的信息的校验和,并和附加其尾部的校验和比较,从而判断出接收到的信息是否正确。比如说,在mod 256中,我们选择的校验和函数仅是各个字节的和,则请看下面,所有的数字都是十进制的。

    信息  :                          6    23     4

    信息加校验和 :           6    23     4    33

    传输后的信息 :           6    27     4    33 


In the above, the second byte of the message was corrupted from 23 to 27 by the communications channel. However, the receiver can detect this by comparing the transmitted checksum (33) with the computer checksum of 37 (6 + 27 + 4). If the checksum itself is corrupted, a correctly transmitted message might be incorrectly identified as a corrupted one. However, this is a safe-side failure. A dangerous-side failure occurs where the message and/or checksum is corrupted in a manner that results in a transmission that is internally consistent. Unfortunately, this possibility is completely unavoidable and the best that can be done is to minimize its probability by increasing the amount of information in the checksum (e.g. widening the checksum from one byte to two bytes).

如上,消息的第二字节"23"由于信道干扰变成了27,然而接收者能够通过比较传输过来的校验和值(33)同计算出来的校验和值 37(6 + 27 + 4)检测这种变化。同理,如果校验和自身被干扰了,则正确的信息可能被验证为错误的,然而这是一种良性的误判。恶性的 误判则发生在信息和/或校验和被这样的方式干扰——传输结果的内部一致。不幸的是这样的误判不可避免,我们能做的是通过增加校验和中信息的数量(如加宽校验和从1byte到2byte )来使这样的可能性最小化。


Other error detection techniques exist that involve performing complex transformations on the message to inject it with redundant information. However, this document addresses only CRC algorithms, which fall into the class of error detection algorithms that leave the data intact and append a checksum on the end. i.e.:

其它错误检测技术通过对信息的复杂变换,将冗余信息加入其中。但是, 本文只讲CRC 算法——一种可归类为使数据保持原状并在其后附加校验和的算法。例如:

<原始信息><校验和>


3.在复杂之前的准备

In the checksum example in the previous section, we saw how a corrupted message was detected using a checksum algorithm that simply sums the bytes in the message mod 256:

      在前面的校验和例子里,我们看见了被干扰了的信息是如何通过校验和(简单的将字节以mod256相加)被检测出来。

    信息  :                          6    23     4

    信息加校验和 :           6    23     4    33

    传输后的信息 :           6    27     4    33 


A problem with this algorithm is that it is too simple. If a number of random corruptions occur, there is a 1 in 256 chance that they will not be detected. For example:

但这个算法过于简单了,一个随机的干扰有1/256的概率使其不会被检测出来,比如:

   信息:                   6 23  4
信息加校验和: 6 23 4 33
传输后的信息: 8 20 5 33


To strengthen the checksum, we could change from an 8-bit register to a 16-bit register (i.e. sum the bytes mod 65536 instead of mod 256) so as to apparently reduce the probability of failure from 1/256 to 1/65536. While basically a good idea, it fails in this case because the formula used is not sufficiently "random"; with a simple summing formula, each incoming byte affects roughly only one byte of the summing register no matter how wide it is. For example, in the second example above, the summing register could be a Megabyte wide, and the error would still go undetected. This problem can only be solved by replacing the simple summing formula with a more sophisticated formula that causes each incoming byte to have an effect on the entire checksum register.

为了加强校验和,我们可以通过将8为寄存器改为16位寄存器(比如将字节以mod65536相加替代以mod256相加)来降低检测失败的概率为1/65536。这仅是一个简单的好想法,他的不足在于不够“随机”;在这个的简单算法里,不论这个校验和寄存器有多长,接收到的每一个字节只会影响校验和寄存器的一个字节。比如在上面的第二个例子里,即使校验和寄存器达到了兆字节宽,错误仍然检测不出来。这个问题只能通过引入一种使接收到字节能够对整个校验和寄存器造成的影响的更复杂的算法来解决。


Thus, we see that at least two aspects are required to form a strong checksum function:

因此,我们意识到至少有两方面影响了校验和函数的强健性: 


宽度(WIDTH)

A register width wide enough to provide a low a-priori probability of failure (e.g. 32-bits gives a 1/2^32 chance of failure).

寄存器宽度足够预先提供一个低的失败可能性(e.g. 32-bits gives a 1/2^32 chance of failure) 


扰乱度(CHAOS):

A formula that gives each input byte the potential to change any number of bits in the register.

通过某个公式使每一位接收到的字节都有改变寄存器内任何bit位的可能。 


Note: The term "checksum" was presumably used to describe early summing formulas, but has now taken on a more general meaning encompassing more sophisticated algorithms such as the CRC ones. The CRC algorithms to be described satisfy the second condition very well, and can be configured to operate with a variety of checksum widths.

Note: 术语"校验和"被认为用来描述早期的相加的校验方式,但是现在有了更广泛的意义,包括了更先进的算法,比如CRC算法。CRC算法被认为能很好满足第二个条件,并能在不同的校验和宽度上得到运用。 


4.CRC算法的基本思想 

Where might we go in our search for a more complex function than summing? All sorts of schemes spring to mind. We could construct tables using the digits of pi, or hash each incoming byte with all the bytes in the register. We could even keep a large telephone book on-line, and use each incoming byte combined with the register bytes to index a new phone number which would be the next register value. The possibilities are limitless.

我们应从何处开始来寻找比相加更复杂的函数呢?各种各样的想法涌入脑中。我们可以用pi值构建一张表,或用寄存器的每一位哈希(hash )接收到的字节。我们甚至可以保有一本巨大的“电话簿”,用接收到的字节结合寄存器中的字节来索引一个号码作为下一个寄存器中的值。可行的方案很多。 


However, we do not need to go so far; the next arithmetic step suffices. While addition is clearly not strong enough to form an effective checksum, it turns out that division is, so long as the divisor is about as wide as the checksum register.

但现在 ,我们不必想太远,接下来的算法步骤就足够了。加法明显的不够强大来形成一种有效的校验和机制,但除法却可以。 只要除数和校验和寄存器大约一样宽就行。 


The basic idea of CRC algorithms is simply to treat the message as an enormous binary number, to divide it by another fixed binary number, and to make the remainder from this division the checksum. Upon receipt of the message, the receiver can perform the same division and compare the remainder with the "checksum" (transmitted remainder).

CRC算法的基本思想简单地就是将信息看成是一个大的二进制数,然后用另一个固定的二进制数来除它,得到余数。接收方用同样的除法来除接收到的信息,将得到的余数同传输来的校验和(一个余数)进行比较。 


Example: Suppose the the message consisted of the two bytes (6,23) as in the previous example. These can be considered to be the hexadecimal number 0617 which can be considered to be the binary number 0000-0110-0001-0111. Suppose that we use a checksum register one-byte wide and use a constant divisor of 1001, then the checksum is the remainder after 0000-0110-0001-0111 is divided by 1001. While in this case, this calculation could obviously be performed using common garden variety 32-bit registers, in the general case this is messy. So instead, we'll do the division using good-'ol long division which you learned in school (remember?). Except this time, it's in binary:

 例子:如同前面的例子一样,假定信息由两个字节(6,23 )组成,16进制是0617 ,二进制是0000-0110-0001-0111。同时还假定使用用一字节宽的校验和寄存器 ,除数恒为1001。 那么校验和就是0000-0110-0001-0111除以1001的余数。者显然可以用一般的32位寄存器来完成计算,但大多数情况下这样比较麻烦。所以,我们用长除法 ,这在学校里学过(还记得吗?)。只是本次是二进制了。

                      ...0000010101101 = 00AD =  173 = QUOTIENT(商)
                  ____-___-___-___-
9= 1001 ) 0000011000010111 = 0617 = 1559 = DIVIDEND(被除数)
除数          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 = REMAINDER(余数)


In decimal this is "1559 divided by 9 is 173 with a remainder of 2".

在十进制里为1559/9=173 余2。


Although the effect of each bit of the input message on the quotient is not all that significant, the 4-bit remainder gets kicked about quite a lot during the calculation, and if more bytes were added to the message (dividend) it's value could change radically again very quickly. This is why division works where addition doesn't.

虽然得到信息的每一bit对商的影响并不都一样明显,但4bit的余数却在计算时不停变换。并且如果更多的字节加入信息(被除数),余数的值会再次迅速的发生巨大变化。这就是加法办不到的地方。


In case you're wondering, using this 4-bit checksum the transmitted message would look like this (in hexadecimal): 06172 (where the 0617 is the message and the 2 is the checksum). The receiver would divide 0617 by 9 and see whether the remainder was 2.

此时你能想象的到,用4bit校验的信息将会这样被传输(16进制):06172(0617是信息,2是校验和),接收器者用9来除0617,看余数是否为2。



5.多项式算术

While the division scheme described in the previous section is very very similar to the checksumming schemes called CRC schemes, the CRC schemes are in fact a bit weirder, and we need to delve into some strange number systems to understand them.

前面讲的除法方式已经很像CRC算法了,CRC算法实际上比他稍微麻烦一点,我们需要探讨一些奇特的数字系统来理解它。


The word you will hear all the time when dealing with CRC algorithms is the word "polynomial". A given CRC algorithm will be said to be using a particular polynomial, and CRC algorithms in general are said to be operating using polynomial arithmetic. What does this mean?

CRC 算法里时你将经常听见多项式一词。一个特定的 CRC 算法被说成是用一个特别的多项式,CRC 算法被普遍认为是一种多项是算法,这是什么意思呢?


Instead of the divisor, dividend (message), quotient, and remainder (as described in the previous section) being viewed as positive integers, they are viewed as polynomials with binary coefficients. This is done by treating each number as a bit-string whose bits are the coefficients of a polynomial. For example, the ordinary number 23 (decimal) is 17 (hex) and 10111 binary and so it corresponds to the polynomial:

除数,被除数,商,余数在这里被看成是有二进制系数的多项式而不是正整数。这是因为将每一个数看作是比特串(bit-string ),比特位就是多项式系数。比如,23(dec)是17(hex)和10111(bin),所以多项式形式为:

1*x^4 + 0*x^3 + 1*x^2 + 1*x^1 + 1*x^0

或更简单的写为:

                                                  x^4 + x^2 + x^1 + x^0


Using this technique, the message, and the divisor can be represented as polynomials and we can do all our arithmetic just as before, except that now it's all cluttered up with Xs. For example, suppose we wanted to multiply 1101 by 1011. We can do this simply by multiplying the polynomials:

用这种方法,信息和除数可看成是多项式,并且我们可以用前面使用的算术方法,只是被写成了 Xs的形式。比如,我们想将1101 和 1011相乘。则我们将如下多项式相乘:

(x^3 + x^2 + x^0)(x^3 + x^1 + 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 


At this point, to get the right answer, we have to pretend that x is 2 and propagate binary carries from the 3*x^3 yielding:

这时,为了得到正确的答案,我们不得不假设x为2,将3*x^3进位得: 

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


It's just like ordinary arithmetic except that the base is abstracted and brought into all the calculations explicitly instead of being there implicitly. So what's the point?

这就像是普通的算术,只不过基数被抽象化了,由此造成除法计算显得不够显式, 这样有什么意义呢?


The point is that IF we pretend that we DON'T know what x is, we CAN'T perform the carries. We don't know that 3*x^3 is the same as x^4 + x^3 because we don't know that x is 2. In this true polynomial arithmetic the relationship between all the coefficients is unknown and so the coefficients of each power effectively becomestrongly typed; coefficients of x^2 are effectively of a different type to coefficients of x^3.

意义在于如果我们假定不知道x是多少,我们就不能做进位运算,我们就不知道 3*x^3与x^4 + x^3 等价,因为我们不知道x是2。在这个真多项式算术中,系数间的关系是未知的,因此每个幂(power )的系数变成了强类型;这样x^2 的系数的对于x^3就是一种不同的类型。


With the coefficients of each power nicely isolated, mathematicians came up with all sorts of different kinds of polynomial arithmetics simply by changing the rules about how coefficients work. Of these schemes, one in particular is relevant here, and that is a polynomial arithmetic where the coefficients are calculated MOD 2 and there is no carry; all coefficients must be either 0 or 1 and no carries are calculated. This is called "polynomial arithmetic mod 2". Thus, returning to the earlier example:

针对不同的幂的系数完全无关这一点,数学家提出了各种各样的多项式算术方法,这些算术方法简单的通过改变系数的运算的法法则来解决上述问题。在这些方法中有一种和crc相关,是一种将系数通过模2和计算,没有进位;所有系数必须是0或1,无进位。被称作“多项式模2和算法”("polynomial arithmetic mod 2")。因此,回到早先的例子中:

(x^3 + x^2 + x^0)(x^3 + x^1 + 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


Under the other arithmetic, the 3*x^3 term was propagated using the carry mechanism using the knowledge that x=2. Under "polynomial arithmetic mod 2", we don't know what x is, there are no carries, and all coefficients have to be calculated mod 2. Thus, the result becomes:

在其他算术方式下, 3*x^3在知道x="2"的情况下来进位,在“多项式模2和算法”下,我们不知道x是几,这里没有进位,所有系数通过模2和计算。因此,结果变为:

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


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.

因此多项式模2和算法仅仅是没有进位的二进制模2算法。虽然它为分析crc和纠错算法提供了有用的数学机理,但由于其没有进一步的内容并显得有些繁缛,所以在随后的文章中不再阐述,取而代之的是与其同型的算法:没有进位的二进制算术。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值