柚子快報(bào)激活碼778899分享:CRC校驗(yàn)算法詳解
柚子快報(bào)激活碼778899分享:CRC校驗(yàn)算法詳解
一、關(guān)于CRC的介紹
????????數(shù)據(jù)在傳輸過(guò)程(比如通過(guò)網(wǎng)線在兩臺(tái)計(jì)算機(jī)間傳文件)中,由于傳輸信道的原因,可能會(huì)有誤碼現(xiàn)象(比如說(shuō)發(fā)送數(shù)字5但接收方收到的卻是6),方法發(fā)送額外的數(shù)據(jù)讓接收方校驗(yàn)是否正確,這就是數(shù)據(jù)校驗(yàn)。常用的校驗(yàn)方法是和校驗(yàn),就是將傳送的數(shù)據(jù)(按字節(jié)方式)加起來(lái)計(jì)算出數(shù)據(jù)的總和,并將總和傳給接收方,接收方收到數(shù)據(jù)后也計(jì)算總和,并與收到的總和比較看是否相同。如果傳輸中出現(xiàn)誤碼,那么總和一般不會(huì)相同,從而知道有誤碼產(chǎn)生,可以讓發(fā)送方再發(fā)送一遍數(shù)據(jù)。
????????CRC即循環(huán)冗余校驗(yàn)碼(Cyclic Redundancy Check):數(shù)據(jù)通信領(lǐng)域中最常用的一種差錯(cuò)校驗(yàn)碼,其信息字段和校驗(yàn)字段長(zhǎng)度可以任意指定,但要求通信雙方定義的CRC標(biāo)準(zhǔn)一致。
二、工作原理
1.CRC原理
????????在K位信息碼(目標(biāo)發(fā)送數(shù)據(jù))后再拼接R位校驗(yàn)碼,使整個(gè)編碼長(zhǎng)度為N位,因此這種編碼也叫(N,K)碼。通俗的說(shuō),就是在需要發(fā)送的信息后面附加一個(gè)數(shù)(即校驗(yàn)碼),生成一個(gè)新的發(fā)送數(shù)據(jù)發(fā)送給接收端。這個(gè)數(shù)據(jù)要求能夠使生成的新數(shù)據(jù)被一個(gè)特定的數(shù)整除。這里的整除需要引入模 2除法的概念,CRC校驗(yàn)的過(guò)程
(1)選定一個(gè)標(biāo)準(zhǔn)除數(shù)(K位二進(jìn)制數(shù)據(jù)串)
(2)在要發(fā)送的數(shù)據(jù)(m位)后面加上K-1位0,然后將這個(gè)新數(shù)(M+K-1位)以模2除法的方式除以上面這個(gè)標(biāo)準(zhǔn)除數(shù),所得到的余數(shù)也就是該數(shù)據(jù)的CRC校驗(yàn)碼(注:余數(shù)必須比除數(shù)少且只少一位,不夠就補(bǔ)0)
(3)將這個(gè)校驗(yàn)碼附在原m位數(shù)據(jù)后面,構(gòu)成新的M+K-1位數(shù)據(jù),發(fā)送給接收端。
(4)接收端將接收到的數(shù)據(jù)除以標(biāo)準(zhǔn)除數(shù),如果余數(shù)為0則認(rèn)為數(shù)據(jù)正確。
????????注意:CRC校驗(yàn)中有兩個(gè)關(guān)鍵點(diǎn):一是要預(yù)先確定一個(gè)發(fā)送端和接收端都用來(lái)作為除數(shù)的二進(jìn)制比特串(或多項(xiàng)式);二是把原始幀與上面選定的除進(jìn)行二進(jìn)制除法運(yùn)算,計(jì)算出FCS。前者可以隨機(jī)選擇,也可按國(guó)際上通行的標(biāo)準(zhǔn)選擇,但最高位和最低位必須均為“1”
實(shí)例:對(duì)于數(shù)據(jù)10110011(16#B3),以指定除數(shù)110011求它的CRC校驗(yàn)碼,其過(guò)程如下:
2.CRC校驗(yàn)碼的計(jì)算
????????這里需要知道幾個(gè)組成部分或者說(shuō)計(jì)算概念:多項(xiàng)式公式、多項(xiàng)式簡(jiǎn)記式、數(shù)據(jù)寬度、初始值、結(jié)果異或值、輸入值反轉(zhuǎn)、輸出值反轉(zhuǎn)、參數(shù)模型。
(1)多項(xiàng)式公式
????????對(duì)于CRC標(biāo)準(zhǔn)除數(shù),一般使用多項(xiàng)式(或二項(xiàng)式)公式表示,如上例中除數(shù)11011的二項(xiàng)式為G(X)=X4+X3+X+1,X的指數(shù)就代表了該bit位上的數(shù)據(jù)為1,(最低位為0)。這里特別注意一下位數(shù)問(wèn)題,除數(shù)的位數(shù)為二項(xiàng)式最高次冪+1(4+1=5),這個(gè)很重要。
(2)多項(xiàng)式簡(jiǎn)記式
????????通過(guò)對(duì)CRC的基本了解我們知道,多項(xiàng)式的首尾必定為1,而這個(gè)1的位置在下一步計(jì)算一定為0,所以就把前面這個(gè)1給省略掉了,出現(xiàn)了一個(gè)叫簡(jiǎn)記式的東西,如上例中除數(shù)11011的簡(jiǎn)記式為1011,很多看過(guò)CRC高級(jí)語(yǔ)言源碼的人會(huì)知道,對(duì)于CRC_16標(biāo)準(zhǔn)下G(X)=X16+X15+X2+1(16#18005)的poly值實(shí)際上是8005,這里使用的就是簡(jiǎn)記式。后面會(huì)對(duì)這個(gè)用法做一個(gè)說(shuō)明。
(3)數(shù)據(jù)寬度
????????數(shù)據(jù)寬度指的就是CRC校驗(yàn)碼的長(zhǎng)度(二進(jìn)制位數(shù)),知道了CRC的運(yùn)算概念和多項(xiàng)式,就可以理解這個(gè)概念了,CRC長(zhǎng)度始終要比除數(shù)位數(shù)少1,與簡(jiǎn)記式長(zhǎng)度是一致的。
????????以上三個(gè)數(shù)據(jù)就是我們經(jīng)常能夠用到的基本數(shù)據(jù)
(4)初始值與結(jié)果異或值
????????在一些標(biāo)準(zhǔn)中,規(guī)定了初始值,則數(shù)據(jù)在進(jìn)行上述二項(xiàng)式運(yùn)算之前,需要先將要計(jì)算的數(shù)據(jù)與初始值的最低字節(jié)進(jìn)行異或,然后再與多項(xiàng)式進(jìn)行計(jì)算。
????????而在結(jié)果異或值不為零的情況下,則需要將計(jì)算得到的CRC結(jié)果值再與結(jié)果異或值進(jìn)行一次異或計(jì)算,得到的最終值才是我們需要的CRC校驗(yàn)碼。
這里可以看出,初始值與結(jié)果值的位數(shù)要求與數(shù)據(jù)寬度一致。
(5)輸入值反轉(zhuǎn)與輸出值反轉(zhuǎn)
????????輸入值反轉(zhuǎn)的意思是在計(jì)算之前先將二項(xiàng)式反轉(zhuǎn),然后再用得到的新值和數(shù)據(jù)進(jìn)行計(jì)算。如對(duì)于G(X)=X16+X15+X2+1(16#18005),其正向值為1 1000 0000 0000 0101,反轉(zhuǎn)值則為1010 0000 0000 0001 1
????????輸出值反轉(zhuǎn)則是將最終得到的CRC結(jié)果反轉(zhuǎn)。
????????通常,輸入值反轉(zhuǎn)后的結(jié)果值也會(huì)是反轉(zhuǎn)的,所以這兩個(gè)選項(xiàng)一般是同向的,我們只有在在線CRC計(jì)算器中會(huì)看到自由選擇正反轉(zhuǎn)的情況存在。
三、實(shí)現(xiàn)代碼
1. package CRC;
2.
3.
4. public class CRC12 {
5.
6. public static String resultBinaryCRC=null; //crc用二進(jìn)制表示
7. public static String messageBinary=null; //結(jié)果用二進(jìn)制表示
8. public static String messageOct=null; //結(jié)果用十進(jìn)制表示
9. public static int a = 0x180f; // 生成多項(xiàng)式
10. public static int CRCBIT = 12;
11.
12. public static void main(String [] args){
13. String message="2";
14. CRC12 a=new CRC12();
15. a.doCalculate(message);
16.
17. }
18.
19. public void doCalculate(String Num)
20. {
21. String crcTemp = null;//余數(shù)
22. Boolean flag = true;
23. int number = Integer.valueOf(Num); // 發(fā)送的數(shù)據(jù)的十進(jìn)制表示
24. int nextNumber = number << CRCBIT; // 變成了被除數(shù)
25. int NumberMinus = Integer.toBinaryString(nextNumber).length()- Integer.toBinaryString(a).length();// 找出被除數(shù)比除數(shù)多幾個(gè)0
26.
27. int nextNumberString12 = nextNumber >> NumberMinus; // 得到前13位的數(shù)值
28. // 前13位與除數(shù)做異或運(yùn)算
29. while (NumberMinus >=0)
30. {
31. if (flag == true) //設(shè)置boolean目的是保證只運(yùn)行一次代碼
32. {
33. crcTemp = Integer.toBinaryString(nextNumberString12);
34. flag = false;
35. }
36.
37. if (crcTemp.length() == 13) //余數(shù)補(bǔ)0,直到湊齊13位,然后再與生成多項(xiàng)式模2運(yùn)算
38. {
39.
40. nextNumberString12 = Integer.parseInt(crcTemp, 2) ^ a; // 余數(shù)與生成多項(xiàng)式異或運(yùn)算
41. crcTemp = Integer.toBinaryString(nextNumberString12); // 將余數(shù)變成二進(jìn)制表示
42. }
43.
44. if(NumberMinus>0)
45. {crcTemp = crcTemp + "0";}
46. NumberMinus--;
47.
48. }
49.
50. int k=12-crcTemp.length(); //根據(jù)余數(shù)的位數(shù),補(bǔ)0變成12位
51. StringBuilder resultCrc=new StringBuilder(); //創(chuàng)建最終結(jié)果的StringBuilder
52. resultCrc.append(Integer.toBinaryString(Integer.parseInt(Num)));
53. for(int i=0;i 54. { 55. resultCrc.append("0"); 56. } 57. resultCrc.append(crcTemp); 58. setMessageBinary(resultCrc.toString()); 59. setResultBinaryCRC(crcTemp); 60. int temp=Integer.parseInt(messageBinary,2); //二進(jìn)制變成十進(jìn)制表示 61. String aaa=Integer.toHexString(temp); 62. setMessageOct(aaa); 63. 64. 65. System.out.println("你發(fā)送的數(shù)據(jù)十進(jìn)制表示"+Num); 66. System.out.println("你發(fā)送的數(shù)據(jù)二進(jìn)制表示"+Integer.toBinaryString(number)); 67. System.out.println("校驗(yàn)碼"+this.getResultBinaryCRC()); 68. System.out.println("最終發(fā)送數(shù)據(jù)二進(jìn)制表示是"+this.getMessageBinary()); 69. System.out.println("最終發(fā)送數(shù)據(jù)十進(jìn)制表示是"+this.getMessageOct()); 70. 71. } 72. 73. public String getResultBinaryCRC() { 74. return resultBinaryCRC; 75. } 76. 77. public void setResultBinaryCRC(String resultBinaryCRC) { 78. CRC12.resultBinaryCRC = resultBinaryCRC; 79. } 80. 81. public String getMessageBinary() { 82. return messageBinary; 83. } 84. 85. public void setMessageBinary(String messageBinary) { 86. CRC12.messageBinary = messageBinary; 87. } 88. 89. public String getMessageOct() { 90. return messageOct; 91. } 92. 93. public void setMessageOct(String messageOct) { 94. CRC12.messageOct = messageOct; 95. } 96. } ? 柚子快報(bào)激活碼778899分享:CRC校驗(yàn)算法詳解 推薦鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。