CRC32算法详细推导(2)

From: http://blog.csdn.net/sparkliang/article/details/5671977

CRC算法详解(2)

初见 Table-Driven

 

变换到上面的方法后,我们离 table-driven 的方法只有一步之遥了,我们知道一个字节能表示的正整数范围是 0~255,步骤 1 中的计算就是针对 reg 的高 Byte 位进行的,于是可以被提取出来,预先计算并存储到一个有 256 项的表中,于是下面的算法就出炉了,这个和上面的算法本质上并没有什么区别。

[cpp] view plaincopy
  1. #define POLY 0x04C11DB7L // CRC32生成多项式  
  2. static unsigned int crc_table[256];  
  3. unsigned int get_sum_poly(unsigned char data)  
  4. {  
  5.     unsigned int sum_poly = data;  
  6.     sum_poly <<= 24;  
  7.     for(int j = 0; j < 8; j++)  
  8.     {  
  9.         int hi = sum_poly&0x80000000; // 取得reg的最高位  
  10.         sum_poly <<= 1;  
  11.         if(hi) sum_poly = sum_poly^POLY;  
  12.     }  
  13.     return sum_poly;  
  14. }  
  15. void create_crc_table()  
  16. {  
  17.     for(int i = 0; i < 256; i++)  
  18.     {  
  19.         crc_table[i] = get_sum_poly(i&0xFF);  
  20.     }  
  21. }  
  22. // 以byte数据为例  
  23. unsigned int CRC32_3(unsigned int data)  
  24. {  
  25.     unsigned char p[8];  
  26.     memset(p, 0, sizeof(p));  
  27.     memcpy(p, &data, 4);  
  28.     unsigned int reg = 0, sum_poly = 0;  
  29.     for(int i = 0; i < 8; i++)  
  30.     {  
  31.         // 计算步骤1  
  32.         sum_poly = crc_table[(reg>>24)&0xFF];  
  33.         // 计算步骤2  
  34.         reg = (reg<<8)|p[i];  
  35.         reg = reg ^ sum_poly;  
  36.     }  
  37.     return reg;  
  38. }  

更进一步

 

上面的这个算法已经是一个Table-Driven的CRC-32算法了,但是实际上我们看到的CRC校验代码都是如下的形式:<div><div><div style="color:silver;"><strong>[cpp]</strong> <a target=_blank href="http://blog.csdn.net/sparkliang/article/details/5671977#" title="view plain" style="color:rgb(160, 160, 160);">view plain</a><a target=_blank href="http://blog.csdn.net/sparkliang/article/details/5671977#" title="copy" style="color:rgb(160, 160, 160);">copy</a></div></div><ol start="1" style="color:rgb(92, 92, 92);"><li style="color:inherit;"><span style="color:black;">r=0;  </span></li><li><span style="color:black;"><span style="color:rgb(0, 102, 153);">while</span>(len--)  </span></li><li style="color:inherit;"><span style="color:black;">     r = (r<<8) ^ t[(r >> 24) ^ *p++];  </span></li></ol></div> 

下面我们将看看是做了什么转化而做到这一点的。

 

 

首先上述 CRC 算法中,我们需要为原始数据追加 r/8Byte 个 0 , CRC-32 就是 4Byte 。或者我们可以再计算原始数据之后,把 0 放在后面单独计算,像这样:

[cpp] view plaincopy
  1. // 先计算原始数据  
  2. for(int i = 0; i < len; i++)  
  3. {  
  4.         sum_poly = crc_table[(reg>>24)&0xFF];  
  5.         reg = (reg<<8)|p[i];  
  6.         reg = reg ^ sum_poly;  
  7. }  
  8. // 再计算追加的4Byte 0  
  9. for(int i = 0; i < 4; i++)  
  10. {  
  11.         reg = (reg<<8) ^ crc_table[(reg>>24)&0xFF];  
  12. }  

这看起来已经足够好了,而事实上我们可以继续向下进行以免去为了附加的 0 而进行计算。在上面算法中,最后的 4 次循环是为了将输入数据的最后 r/8 位都移出 reg ,因为 0 对 reg 的值并没有丝毫影响。

对于 CRC-32 ,对于任何输入数据 Dn...D8…D5D4…D1 ,第一个 for 循环将 Dn…D8…D5 都依次移入,执行XOR 运算再移出 reg ;并将 D4…D1 都移入了 reg ,但是并未移出;因此最后的 4 次循环是为了将 D4…D1 都移出 reg 。

Di 与 Ri 执行 XOR 运算后值将会更新,设更新后的值表示为 Di’ ,不论执行了多少次 XOR 运算。

如果 reg 初始值是 0 ,那么第一个 for 循环中开始的 4 次循环干的事情就是,把 Dn…Dn-3 移入到 reg 中(与0 做 XOR 结果不变),执行 4 次后 reg 的值就是 Dn.Dn-1.Dn-2.Dn-3 ;

第 5 次循环的结果就是: reg = crc_table[Dn] ^ Dn-1.Dn-2.Dn-3.Dn-4 ;

第 6 次循环的结果就是: reg = crc_table[Dn-1’] ^ Dn-2’.Dn-3’.Dn-4 ; Dn 移出 reg 。

因此上面的计算可以分为 3 个阶段:

1 )前 4 次循环,将 Dn.Dn-1.Dn-2.Dn-3 装入 reg ;

2 )中间的 n-4 次循环,依次将 Di 移入 reg ,在随后的 4 次循环中,依次计算 Di+4 , Di+3 , Di+2 和 Di+1对 Di 的影响;最后移出 reg ;  

3 )最后的 4 次循环,实际上是为了计算 D4 , D3 , D2 和 D1 都能执行第 2 步的过程;

具体考察 Di :

1 ) Di 移入到 reg 中, R1=Di ,接着与 crc_table[R4] 执行 XOR 运算;

2 )循环 4 次后, Di 成为 reg 的最高位 R4 ,并且因为受到了 Dn…Di+1 的影响而更新为 Di’ ;

上面的运算步骤如下面所示,其中 F 是对应得 crc_table[R] 的值。

可以清晰的看到,最后 reg 的高 Byte 是 Di 和 F 之间一次次 XOR 运算的结果。依然根据 XOR 运算的结合律,我们可以分两步走:

1)  先执行 F 之间的 XOR 运算,设结果为 FF ,它就是 reg 的首字节;

2)  然后再直接将 Di 和 FF 进行 XOR 运算,并根据结果查 CRC 表;

3)  计算出 XOR 运算后, Di…Di-3 已经移入 reg ;因此再将查表结果和 (reg<<8) 执行 XOR 运算即可;

这就是方法 2 ,于是我们的 table-driven 的 CRC-32 校验算法就可以写成如下的方式了:

[cpp] view plaincopy
  1. reg = 0;  
  2. for(int i = 0; i < len; i++)  
  3. {  
  4.     reg = (reg<<8) ^ crc_table[(reg>>24)&0xFF ^ p[i]];  
  5. }  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/404154.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每天一点Swift(五)控制器的生命周期和SizeClass

字数358 阅读19 评论0 喜欢0 初始化init-->awakeFromNib--> prepare a segue --> SB去设置outlets --> viewDidLoad 1. viewDidLoad 在viewDidLoad中&#xff0c;outlets已经被设置&#xff1b;但是几何位置&#xff08;bounds&#xff09;并没有被设置 viewDidLoa…

h264 I帧的判断

From:http://blog.csdn.net/dxpqxb/article/details/13289205 H264数据的NALU 头的格式如图2 所示&#xff1a; F&#xff1a;forbidden_zero_bit.1 位&#xff0c;如果有语法冲突&#xff0c;则为 1。当网络识别此单元存在比特错误时&#xff0c;可将其设为 1&#xff0c;以便…

单硬盘上mac + win7双系统,GUID-GPT分区

首先&#xff0c;当然要介绍下我的环境了。 一、环境介绍 1. 主板是支持UEFI启动的&#xff0c;但是我感觉自己没用到。 2. 我有两个硬盘: hd0: 准备安装mac和win7_x64 hd1: GUID格式&#xff0c;GPT分区&#xff0c;已装有mac10.9.3环境&#xff0c;还有个FAT32的分区&a…

将clover安装到硬盘EFI分区, 解决root device uuid is ...问题

其实说白了&#xff0c;很简单&#xff0c;照着配置图来&#xff0c;一招搞定&#xff0c;但是当你不知道这些配置的时候&#xff0c;将可能耗费你好几天的时间&#xff0c;而且还不一定得到最优解。 附“Clover v2k r2703.pkg"下载地址: http://download.csdn.net/deta…

Silverlight 5 新特性

微软Silverlight 团队在12月9日早上低调的发布了Silverlight 第五个版本-Silverlight 5. Silverlight 5 Available is Here 这也可能是Silverlight最后一个官方主要版本. Silverlight 5 可能作为官方发布最后一个Silverlight 版本. 官方提供各方面支持直到2021年. 支持的时间相…

VMware10出现VMware Workstation 不可恢复错误: (vmx)

在我的VMware10中安装了Ubuntu12&#xff0c; 昨晚还正常关机的呢&#xff0c;今天早上一打开&#xff0c;竟然报错了&#xff0c;错误如图&#xff1a; 上网搜索了下&#xff0c;没有找到比较合适的方法&#xff0c;最后&#xff0c;我在没有卸载VMware的情况下&#xff0c;重…

DB2中ixf文件的导入导出

1. 导出数据 语法&#xff1a;EXPORT TO <文件路径>/文件名.IXF OF IXF SELECT * FROM 表名 2. 导入数据 语法&#xff1a;db2 IMPORT FROM <路径>/<文件名>.IXF OF IXF MODIFIED BY FORCECREATE COMMITCOUNT 10000 REPLACE_CREATE INTO <表名> 简单语…

Android新手入门2016(10)--GridView

本文来自肥宝传说之路&#xff0c;引用必须注明出处&#xff01; GridView跟ListView一样是多控件布局。实现九宫图是最方便的。 还是先看看图&#xff0c;没图说个鸡鸡是不是 如上图&#xff0c;是一种应用方式&#xff0c;在每个格子里面&#xff0c;放入应用图标&#xff0c…

《云计算核心技术剖析》读书笔记之一

http://book.douban.com/subject/6382788/ 通过2周的时间&#xff0c;阅读完了由吴朱华编著的《云计算核心技术剖析》一书。同时国内由CSDN协办的第四届云计算大会要开幕&#xff0c;我在这里把自己写下这本书的读书笔记。这本书是2011年出版&#xff0c;但是在这本书上对微软的…

第四周仿真作业

经过第四周关于交流电机的学习&#xff0c;我们通过对起调速特性的了解&#xff0c;进行仿真&#xff1a; 控制电机带重物上升&#xff0c;从静止加速到800r/min保持800r/min匀速运动0.5s&#xff0c;减速到静止&#xff0c;保持静止状态0.5s&#xff0c;带重物下降&#xff0c…

GVim中以十六进制方式打开文件

在windows下&#xff0c;有时我们想用GVim以十六进制形式来打开一个文件&#xff0c;下面就是不错的方法&#xff0c;将它作为一个右键菜单方式加入&#xff1a; 1. 将"GVim Hex"加入到右键菜单, 将以下内容添加到一个xxx.reg文件&#xff0c;再双击运行一次即可&am…

高性能的智能日志

【编者按】本文作者是 Archanaa Panda &#xff0c;从 2000 以来一直在软件开发&#xff08;构架、设计和编程&#xff09;团队担任 Java / JavaEE 构架师&#xff0c;目前立志于做一个与时俱进的独立的顾问架构师。在本篇文章中&#xff0c;作者通过多个方面为生产环节的日志提…

Android, WindowsPhone7, IOS ,vc2010平台40多套图片滤镜开源

历经三个多月开发&#xff0c;终于完成了这三个库的编码工作。用到的开发语言主要有使用了C&#xff08;含部分Object-c&#xff09;,JAVA,C#。经过检测&#xff0c;目前已正式投入到生产环境中。 为了实现三种语言一种命名方式&#xff0c;我采用了相同的类名&#xff0c;接口…

找到一个比较熟悉Go语言的国内博客

2019独角兽企业重金招聘Python工程师标准>>> 他写了一些不错的Go安装和使用的文章&#xff0c;还参与了一本Go语言书籍的翻译工作&#xff0c;对Go语言相当熟悉。博客地址&#xff1a; http://www.mikespook.com/category/golang-2/ 转载于:https://my.oschina.net/…

解决EditText不能撑满全屏的问题及EditText你应该知道的属性

一般我们要实现去下图一的效果很简单&#xff1a;两个EditText就搞定效果图一&#xff1a;但是我们想让第二个EditText撑满剩余空间怎么做&#xff1f;如效果图二效果图二&#xff1a;解决&#xff1a;使用了ScrollView嵌套LinearLayout&#xff0c;将ScrollView中android:fill…