数据处理 -- CRC32校验算法整理

2024-06-08 15:28

本文主要是介绍数据处理 -- CRC32校验算法整理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CRC(循环冗余校验)技术文档整理

CRC32(Cyclic Redundancy Check 32-bit)是一种常见的校验和算法,广泛应用于网络通信、文件校验等领域。

核心思想

CRC32 利用一种基于二进制多项式的算法,将输入数据视为一个大整数,并通过一个固定的生成多项式进行模除运算,得到的余数即为 CRC 校验和。这个过程有效地将数据压缩为一个固定长度的值,该值可以用于验证数据的完整性。

多项式表示

数据和生成多项式都可以表示为二进制多项式。例如,数据 (1101011011) 可以表示为多项式:

x 10 + x 9 + x 7 + x 5 + x 4 + x 2 + x 1 x^{10} + x^9 + x^7 + x^5 + x^4 + x^2 + x^1 x10+x9+x7+x5+x4+x2+x1

生成多项式

CRC32 使用的生成多项式通常为:

x 32 + x 26 + x 23 + x 22 + x 16 + x 12 + x 11 + x 10 + x 8 + x 7 + x 5 + x 4 + x 2 + x + 1 x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1

其对应的二进制表示为 0x04C11DB7

初始值和最终异或

初始化 CRC 寄存器为 0xFFFFFFFF,最终结果再与 0xFFFFFFFF 进行异或处理。

逐字节处理

对输入数据逐字节进行处理,每处理一个字节时,将其与当前 CRC 值进行异或操作。对每个字节的每一位执行移位和条件异或操作,具体如下:

  • 如果当前 CRC 值的最高位为 1,将 CRC 值左移一位,然后与生成多项式进行异或。
  • 如果最高位为 0,只将 CRC 值左移一位。

得到最终 CRC 值

所有字节处理完毕后,得到的余数即为 CRC 校验和。

具体实现过程

  1. 数据与初始 CRC 值异或:对输入数据的每个字节,与当前 CRC 寄存器的高字节进行异或。

  2. 按位处理数据:将异或后的结果左移一位,并检查最高位是否为 1。如果为 1,则与生成多项式进行异或。如果为 0,则继续左移。这个过程重复 8 次(因为每个字节有 8 位)。

  3. 最终处理:在所有数据处理完成后,将最终的 CRC 值与 0xFFFFFFFF 进行异或。

示例代码

以下是 Python 实现 CRC32 计算的示例代码:

def crc32(data):crc = 0xFFFFFFFFpoly = 0x04C11DB7for byte in data:crc ^= byte << 24for _ in range(8):if crc & 0x80000000:crc = (crc << 1) ^ polyelse:crc <<= 1crc &= 0xFFFFFFFF  # 确保 CRC 结果在 32 位范围内return crc ^ 0xFFFFFFFF# 测试数据
data = b"123456789"
result = crc32(data)
print(f"CRC32: {result:08X}")

生成多项式选择原则

  1. 错误检测能力:不同的生成多项式在检测单比特错误、多比特错误、突发错误等方面的能力不同。选择合适的生成多项式可以提高错误检测的效率。
  2. 多项式长度:多项式的长度(即阶数)决定了 CRC 校验和的长度。常见的长度有 CRC-8、CRC-16、CRC-32 等。
  3. 标准化和兼容性:选择标准化的生成多项式可以确保不同设备和系统之间的兼容性。

常用生成多项式

CRC-8

  • 多项式: x 8 + x 2 + x + 1 x^8 + x^2 + x + 1 x8+x2+x+1
  • 二进制表示:0x07
  • 应用:常用于小型数据包和简单通信协议。

CRC-16

  • CRC-16-IBM
    • 多项式: x 16 + x 15 + x 2 + 1 x^{16} + x^{15} + x^2 + 1 x16+x15+x2+1
    • 二进制表示:0x8005
    • 应用:广泛用于工业协议,如Modbus。
  • CRC-CCITT (XModem)
    • 多项式: x 16 + x 12 + x 5 + 1 x^{16} + x^{12} + x^5 + 1 x16+x12+x5+1
    • 二进制表示:0x1021
    • 应用:用于电信和网络协议。

CRC-32

  • 多项式: x 32 + x 26 + x 23 + x 22 + x 16 + x 12 + x 11 + x 10 + x 8 + x 7 + x 5 + x 4 + x 2 + x + 1 x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
  • 二进制表示:0x04C11DB7
  • 应用:广泛用于网络通信、文件校验和压缩文件格式,如ZIP和RAR。

规范和标准

许多协议和标准定义了特定的生成多项式,以确保不同实现之间的兼容性。以下是一些重要的标准和协议中定义的生成多项式:

  1. 以太网

    • 使用的生成多项式:0x04C11DB7(CRC-32)
    • 用于帧校验序列(FCS)。
  2. HDLC

    • 使用的生成多项式:0x8408(CRC-16-CCITT)
    • 用于帧校验序列。
  3. USB

    • 使用的生成多项式:0x8005(CRC-16-IBM)
    • 用于数据包校验。
  4. ZIP文件格式

    • 使用的生成多项式:0x04C11DB7(CRC-32)
    • 用于文件压缩和解压缩过程中的数据完整性校验。

选择生成多项式的建议

  • 应用场景:根据具体的应用场景选择生成多项式。例如,工业控制和通信协议通常选择 CRC-16,而网络协议和文件压缩通常选择 CRC-32。
  • 标准化:尽量选择标准化的生成多项式,以确保不同系统和设备之间的兼容性。
  • 错误检测需求:根据对错误检测能力的需求,选择适当的多项式长度和形式。例如,对于高可靠性要求的系统,可以选择更复杂和更长的生成多项式。

总之,生成多项式的选择对 CRC 算法的性能和可靠性有重要影响。在选择时,应考虑应用场景、标准化要求和错误检测能力。

按字节处理的示例说明

假设我们有一个数据字节 0x31,我们使用生成多项式 0x04C11DB7 来计算 CRC32 校验和。

  1. 初始设置

    • 数据:0x31(ASCII 编码为 00110001
    • 生成多项式:0x04C11DB7
    • 初始 CRC 值:0xFFFFFFFF
  2. 处理数据

    • 第一步:crc = 0xFFFFFFFF ^ (0x31 << 24) = 0xCEFFFFFF
    • 第二步:逐位处理,从最高位到最低位,按上述规则进行移位和条件异或。
      • 位 1:0xCEFFFFFF 高位为 1,左移后异或多项式:0x9DFFFFFE ^ 0x04C11DB7 = 0xD229A1C9
      • 位 2:0xD229A1C9 高位为 1,左移后异或多项式:0xA4534392 ^ 0x04C11DB7 = 0xE7568A51
      • 位 3:0xE7568A51 高位为 1,左移后异或多项式:0xCEAD14A2 ^ 0x04C11DB7 = 0x8F07B5F3
      • 位 4:0x8F07B5F3 高位为 1,左移后异或多项式:0x1E0F6BE6 ^ 0x04C11DB7 = 0x5AF0C5A9
      • 位 5:0x5AF0C5A9 高位为 0,仅左移:0xB5E18B52
      • 位 6:0xB5E18B52 高位为 1,左移后异或多项式:0x6BC316A4 ^ 0x04C11DB7 = 0x2D345678
      • 位 7:0x2D345678 高位为 0,仅左移:0x5A68ACF0
      • 位 8:0x5A68ACF0 高位为 0,仅左移:0xB4D159E0
    • 处理后的中间结果:0xB4D159E0
  3. 处理所有字节后

    • 逐字节进行异或和移位操作,最终得到中间 CRC 值。
  4. 最终处理

    • 最终中间 CRC 值:0xB4D159E0
    • 将中间 CRC 值与 0xFFFFFFFF 进行异或,得到最后的 CRC32 校验和:0x4B2EA61F

分布式运算和并行计算

CRC 算法通常用于串行处理数据,但在需要处理大数据集或高性能应用时,可以通过分布式运算和并行计算来优化计算效率。以下是一些优化方法:

  1. 数据分块

    • 将大数据集分成多个块,分别计算每个块的 CRC 值。
    • 每个块的计算可以独立进行,从而可以在多核处理器或多台机器上并行处理。
  2. 并行处理

    • 使用多线程或多进程技术,在同一台机器上并行计算多个数据块的 CRC。
    • 每个线程或进程处理一个数据块,最后将各个块的 CRC 值合并。
  3. 硬件加速

    • 使用专用的硬件,如 FPGA 或 GPU,加速 CRC 计算。
    • 硬件加速器可以在更短的时间内完成大量数据的 CRC 计算。
  4. 增量计算

    • 对于实时数据流,可以使用增量计算的方法,不断更新 CRC 值,而无需重新计算整个数据集。
    • 这种方法特别适用于网络通信中的实时错误检测。

CRC 合并分块计算的例子与原理分析

在实际应用中,我们常常需要将数据分块处理,然后合并各个分块的 CRC 值来得到最终的 CRC 值。这涉及到一些特定的数学原理和处理步骤。下面我们详细解释这些步骤,并给出具体的代码实现。

分块计算 CRC 的原理

CRC(循环冗余校验)的基础是多项式代数,其中数据和生成多项式都被表示为二进制多项式。CRC 合并的核心思想是如何将两个分开的 CRC 结果合并成一个整体的 CRC 值。为了理解这一点,我们需要回顾以下几个关键点:

多项式表示

数据和生成多项式都可以表示为多项式。例如,数据字节 (11010110) 可以表示为:

x 7 + x 6 + x 4 + x 2 + x 1 x^7 + x^6 + x^4 + x^2 + x^1 x7+x6+x4+x2+x1

多项式除法

CRC 的计算本质上是多项式除法的过程,将数据多项式除以生成多项式,得到的余数即为 CRC 校验和。

位移和余数

在分块处理数据时,每个块的 CRC 计算会影响到整个数据的最终 CRC 值。这是因为每个数据块在多项式除法中相当于一个部分商,必须通过适当的位移和余数计算来合并这些部分商。

生成多项式

CRC32 使用的生成多项式是:

x 32 + x 26 + x 23 + x 22 + x 16 + x 12 + x 11 + x 10 + x 8 + x 7 + x 5 + x 4 + x 2 + x + 1 x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1

其对应的二进制表示为 0x04C11DB7

反射式 CRC 和 0xEDB88320

0xEDB883200x04C11DB7 的位反射形式,用于优化计算:

  • 正向生成多项式:0x04C11DB7
  • 位反射生成多项式:0xEDB88320

使用位反射形式可以简化硬件实现,并且在处理低位优先的数据时更为方便。通过位反射,我们可以使用相同的逻辑来处理高位优先和低位优先的数据。

分块计算的详细示例

假设我们有如下数据:“123456789”,我们将其分为两个块进行处理:

  • 块1:"1234" (ASCII 编码为 0x31 0x32 0x33 0x34
  • 块2:"56789" (ASCII 编码为 0x35 0x36 0x37 0x38 0x39
计算块1的 CRC
  1. 初始 CRC 值:0xFFFFFFFF

  2. 处理字节 0x31("1"的ASCII编码):

    • CRC = 0xFFFFFFFF ^ (0x31 << 24) = 0xCEFFFFFF
    • 执行 8 次移位和条件异或:
      • 位1:0x9DFFFFFE ^ 0x04C11DB7 = 0xD229A1C9
      • 位2:0xA4534392 ^ 0x04C11DB7 = 0xE7568A51
      • 位3:0xE7568A51 ^ 0x04C11DB7 = 0x8F07B5F3
      • 位4:0x1E0F6BE6 ^ 0x04C11DB7 = 0x5AF0C5A9
      • 位5:0x5AF0C5A9 高位为0,仅左移:0xB5E18B52
      • 位6:0xB5E18B52 ^ 0x04C11DB7 = 0x6BC316A4
      • 位7:0x6BC316A4 高位为0,仅左移:0xD7862D48
      • 位8:0xD7862D48 ^ 0x04C11DB7 = 0xA1E10F77
  3. 继续处理其余字节,得到块1的 CRC 中间值 0xC814E496

计算块2的 CRC
  1. 初始 CRC 值:0xFFFFFFFF
  2. 按照上述步骤逐字节处理,得到块2的 CRC 中间值 0x5A5AA6F4
合并块的 CRC 值

为了合并两个块的 CRC 值,我们需要对第一个块的 CRC 值进行预处理,并结合第二个块的 CRC 值。

预处理块1的 CRC 值

我们需要将块1的 CRC 值根据块2的长度(5个字节)进行位移和多项式余数计算。具体步骤如下:

  1. 块1的 CRC 值 0xC814E496 进行 5 字节(40位)的预处理:
    • 对每一位进行条件异或和移位,最终得到预处理后的 CRC 值。
合并块1和块2的 CRC 值
  1. 使用预处理后的 CRC 值与块2的 CRC 值进行 XOR 操作。
  2. 按照具体的多项式合并逻辑,计算得到最终的 CRC 值。
代码实现示例

以下是一个具体的代码实现,用于计算和合并分块 CRC 值:

import zlibdef crc32_combine(crc1, crc2, len2):# 预处理第一个 CRC 值,长度为 len2 的数据块大小for _ in range(len2 * 8):if crc1 & 1:crc1 = (crc1 >> 1) ^ 0xEDB88320else:crc1 >>= 1return crc1 ^ crc2def calculate_crc32(data):return zlib.crc32(data) & 0xFFFFFFFFdef calculate_crc32_in_chunks(data, chunk_size):chunks = [data[i:i + chunk_size] for i in range(0, len(data), chunk_size)]crc = 0for chunk in chunks:chunk_crc = calculate_crc32(chunk)crc = crc32_combine(crc, chunk_crc, len(chunk))return crc# 测试数据
data = b"123456789"
chunk_size = 4  # 将数据分成两个块
result = calculate_crc32_in_chunks(data, chunk_size)
print(f"CRC32: {result:08X}")
代码解释
  • crc32_combine:该函数用于合并两个分块 CRC 值,len2 是第二个数据块的长度。
  • calculate_crc32:函数计算单个数据块的 CRC 值。
  • calculate_crc32_in_chunks:函数将数据分块并计算每块的 CRC 值,最后合并得到整体的 CRC 值。

通过上述示例,可以更好地理解如何分块计算和合并 CRC 值,以确保数据完整性检测的准确性。

这篇关于数据处理 -- CRC32校验算法整理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1042567

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

dp算法练习题【8】

不同二叉搜索树 96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n = 3输出:5 示例 2: 输入:n = 1输出:1 class Solution {public int numTrees(int n) {int[] dp = new int

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯: