CRC的数学原理


CRC(Cyclic Redundancy Check,循环冗余校验)是一种 基于多项式除法的差错检测技术,广泛应用于数据传输和存储场景(如网络通信、磁盘存储、串口传输等),用于判断数据在传输或存储过程中是否发生了比特翻转等错误。

Part 1. CRC概述

核心原理

CRC的本质是将数据看作二进制多项式,通过模2除法计算余数,将余数作为校验码附加到原始数据后。接收方对包含校验码的完整数据重复相同的计算,如果余数为0,则判定数据无错;否则判定数据出错。

关键概念
  1. 原始数据:待传输的二进制序列,对应多项式 D ( x ) D(x) D(x)
  2. 生成多项式:预先约定的固定二进制序列,对应多项式 G ( x ) G(x) G(x),是CRC的核心参数(如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)。
  3. 校验码(CRC码):原始数据左移 r r r 位( r r r 是生成多项式的阶数,即最高次幂)后,除以生成多项式得到的余数,长度为 r r r 位。
计算步骤(发送方)
  1. 设生成多项式 G ( x ) G(x) G(x) 的阶数为 r r r,将原始数据 D ( x ) D(x) D(x) 左移 r r r 位,得到 D ′ ( x ) = D ( x ) × x r D'(x) = D(x) \times x^r D(x)=D(x)×xr(相当于在原始数据末尾补 r r r 个0)。
  2. D ′ ( x ) D'(x) D(x) G ( x ) G(x) G(x) 进行模2除法(模2运算规则:加法无进位,减法无借位,即 0 + 0 = 0 , 0 + 1 = 1 , 1 + 0 = 1 , 1 + 1 = 0 0+0=0, 0+1=1, 1+0=1, 1+1=0 0+0=0,0+1=1,1+0=1,1+1=0)。
  3. 得到余数 R ( x ) R(x) R(x),其长度为 r r r 位(不足补0),这就是CRC校验码。
  4. 将校验码附加到原始数据末尾,得到传输数据 T ( x ) = D ( x ) × x r + R ( x ) T(x) = D(x) \times x^r + R(x) T(x)=D(x)×xr+R(x)
校验步骤(接收方)
  1. 接收传输数据 T ( x ) T(x) T(x)
  2. T ( x ) T(x) T(x) 与生成多项式 G ( x ) G(x) G(x) 进行模2除法。
  3. 若余数为0 → 数据无错;若余数不为0 → 数据出错。

常见CRC标准

不同的生成多项式对应不同的CRC标准,适用于不同场景:

标准生成多项式(二进制)特点应用场景
CRC-8 100000111 100000111 100000111 x 8 + x 2 + x + 1 x^8+x^2+x+1 x8+x2+x+1短校验码,计算快小数据块校验
CRC-16 10001000000100001 10001000000100001 10001000000100001 x 16 + x 15 + x 2 + 1 x^{16}+x^{15}+x^2+1 x16+x15+x2+1经典标准,兼容性好串口通信、Modbus
CRC-3232位标准多项式(见上文)高检错率,抗干扰强以太网、ZIP、磁盘

核心特点

  1. 检错能力强
    • 可以检测出所有奇数个比特错误
    • 可以检测出所有长度小于等于生成多项式阶数的突发错误(突发错误指连续多个比特翻转)。
    • 对长度大于阶数的突发错误,检错概率约为 1 − 2 − r 1 - 2^{-r} 12r r r r 为校验码长度),CRC-32的检错概率接近100%。
  2. 计算高效
    • 可以通过硬件电路(移位寄存器)或软件算法快速实现,适合实时系统。
  3. 局限性
    • 仅能检错,不能纠错:发现错误后,只能要求重传,无法直接修正错误比特。
    • 存在极小概率的“漏检”:不同的原始数据可能生成相同的CRC码,导致错误未被检测到(概率极低,可忽略)。

典型应用场景

  • 网络通信:以太网帧、TCP/UDP数据包的校验。
  • 存储系统:磁盘扇区、光盘数据、压缩文件(ZIP、RAR)的校验。
  • 嵌入式通信:串口、CAN总线、SPI等协议的数据校验。

与其他校验方式的对比

校验方式原理检错能力适用场景
CRC多项式模2除法强(可检测多类错误)实时传输、存储
奇偶校验统计1的个数的奇偶性弱(仅检测奇数个错误)简单低成本场景
校验和字节累加求和取模中等网络协议(如IP头校验)

Part 2. CRC(循环冗余校验)的有效性证明

要证明 CRC(循环冗余校验)的正确性,核心是证明:接收方对无差错的传输数据执行模2除法时,余数必然为0;若余数不为0,则数据一定存在差错

证明过程基于多项式模2运算的代数性质,以下是严谨的推导步骤:

1. 定义核心多项式

首先明确发送方和接收方约定的关键参数:

  • 设原始数据对应的二进制多项式为 D ( x ) D(x) D(x),长度为 k k k 位。
  • 设生成多项式为 G ( x ) G(x) G(x),阶数为 r r r(即最高次项为 x r x^r xr),长度为 r + 1 r+1 r+1 位。
  • 模2运算规则:加法/减法无进位/借位,满足 a + a = 0 a+a=0 a+a=0 a − a = 0 a-a=0 aa=0,等价于异或运算

2. 发送方的编码过程推导

发送方的编码步骤对应多项式运算:

  1. 原始数据左移 r r r 位,等价于多项式乘以 x r x^r xr,得到:
    D ′ ( x ) = D ( x ) ⋅ x r D'(x) = D(x) \cdot x^r D(x)=D(x)xr
    这一步的目的是为校验码预留 r r r 位空间。

  2. D ′ ( x ) D'(x) D(x) 执行模2除法 D ′ ( x ) ÷ G ( x ) D'(x) \div G(x) D(x)÷G(x),根据多项式除法性质,可分解为:
    D ′ ( x ) = Q ( x ) ⋅ G ( x ) + R ( x ) D'(x) = Q(x) \cdot G(x) + R(x) D(x)=Q(x)G(x)+R(x)
    其中:

    • Q ( x ) Q(x) Q(x) 是商多项式;
    • R ( x ) R(x) R(x) 是余数多项式,且 deg ( R ( x ) ) < r \text{deg}(R(x)) < r deg(R(x))<r(余数的阶数一定小于除数的阶数),因此 R ( x ) R(x) R(x) 对应一个 r r r 位二进制数,即 CRC校验码
  3. 发送方将校验码附加到原始数据后,最终传输的多项式为:
    T ( x ) = D ′ ( x ) + R ( x ) T(x) = D'(x) + R(x) T(x)=D(x)+R(x)
    代入上式可得:
    T ( x ) = Q ( x ) ⋅ G ( x ) + R ( x ) + R ( x ) T(x) = Q(x) \cdot G(x) + R(x) + R(x) T(x)=Q(x)G(x)+R(x)+R(x)
    根据模2运算性质 R ( x ) + R ( x ) = 0 R(x)+R(x)=0 R(x)+R(x)=0,因此:
    T ( x ) = Q ( x ) ⋅ G ( x ) \boldsymbol{T(x) = Q(x) \cdot G(x)} T(x)=Q(x)G(x)

    这是CRC正确性的核心等式传输多项式 T ( x ) T(x) T(x) 是生成多项式 G ( x ) G(x) G(x) 的整数倍

3. 接收方的校验过程证明

接收方收到数据后,得到多项式 T ′ ( x ) T'(x) T(x),分两种情况讨论:

情况1:数据无差错, T ′ ( x ) = T ( x ) T'(x)=T(x) T(x)=T(x)

此时代入核心等式:
T ′ ( x ) = Q ( x ) ⋅ G ( x ) T'(x) = Q(x) \cdot G(x) T(x)=Q(x)G(x)
接收方执行模2除法 T ′ ( x ) ÷ G ( x ) T'(x) \div G(x) T(x)÷G(x),余数为:
Remainder [ T ′ ( x ) / G ( x ) ] = Remainder [ Q ( x ) ⋅ G ( x ) / G ( x ) ] = 0 \text{Remainder}[T'(x)/G(x)] = \text{Remainder}[Q(x)\cdot G(x)/G(x)] = 0 Remainder[T(x)/G(x)]=Remainder[Q(x)G(x)/G(x)]=0
结论:无差错时,余数必然为0。

情况2:数据有差错, T ′ ( x ) = T ( x ) + E ( x ) T'(x)=T(x)+E(x) T(x)=T(x)+E(x)

其中 E ( x ) ≠ 0 E(x) \neq 0 E(x)=0错误多项式,对应数据中比特翻转的位置。
此时接收方计算的余数为:
Remainder [ T ′ ( x ) / G ( x ) ] = Remainder [ ( T ( x ) + E ( x ) ) / G ( x ) ] \text{Remainder}[T'(x)/G(x)] = \text{Remainder}[(T(x)+E(x))/G(x)] Remainder[T(x)/G(x)]=Remainder[(T(x)+E(x))/G(x)]
代入 T ( x ) = Q ( x ) ⋅ G ( x ) T(x)=Q(x)\cdot G(x) T(x)=Q(x)G(x),可得:
Remainder [ ( Q ( x ) ⋅ G ( x ) + E ( x ) ) / G ( x ) ] = Remainder [ E ( x ) / G ( x ) ] \text{Remainder}[(Q(x)\cdot G(x)+E(x))/G(x)] = \text{Remainder}[E(x)/G(x)] Remainder[(Q(x)G(x)+E(x))/G(x)]=Remainder[E(x)/G(x)]

  • Remainder [ E ( x ) / G ( x ) ] ≠ 0 \text{Remainder}[E(x)/G(x)] \neq 0 Remainder[E(x)/G(x)]=0,则余数不为0,接收方判定数据出错。
  • Remainder [ E ( x ) / G ( x ) ] = 0 \text{Remainder}[E(x)/G(x)] = 0 Remainder[E(x)/G(x)]=0,则 E ( x ) E(x) E(x) G ( x ) G(x) G(x) 的倍数,此时会发生漏检,但这种情况的概率极低( 1 / 2 r 1/2^r 1/2r),且可通过选择合适的 G ( x ) G(x) G(x) 进一步降低概率。

4. CRC检错能力的补充证明

CRC的强检错能力也可通过多项式性质证明,以两个典型结论为例:

  1. 检测所有奇数个比特错误
    奇数个比特错误对应的错误多项式 E ( x ) E(x) E(x) 有奇数个非零项。
    若生成多项式 G ( x ) G(x) G(x) 包含因子 ( x + 1 ) (x+1) (x+1)(即 G ( 1 ) = 0 G(1)=0 G(1)=0,模2运算下 1 + 1 = 0 1+1=0 1+1=0),则 E ( 1 ) = 1 E(1)=1 E(1)=1(奇数个1相加为1),因此 E ( x ) E(x) E(x) 不能被 G ( x ) G(x) G(x) 整除,余数不为0,错误可被检测。

  2. 检测所有长度 ≤ r \le r r 的突发错误
    突发错误是指连续 b b b 位比特翻转,对应的多项式为 E ( x ) = x i ( 1 + x + x 2 + ⋯ + x b − 1 ) E(x)=x^i(1+x+x^2+\dots+x^{b-1}) E(x)=xi(1+x+x2++xb1),长度 b ≤ r b \le r br
    由于 deg ( E ( x ) ) = i + b − 1 \text{deg}(E(x))=i+b-1 deg(E(x))=i+b1,且 G ( x ) G(x) G(x) 阶数为 r r r b ≤ r b \le r br E ( x ) E(x) E(x) 的最高次项小于 G ( x ) G(x) G(x) 的最高次项,无法被 G ( x ) G(x) G(x) 整除,余数不为0,错误可被检测。

总结

CRC的正确性本质是多项式模2运算的整除性

  • 无差错时,传输多项式是生成多项式的倍数 → 余数为0;
  • 有差错时,错误多项式大概率不是生成多项式的倍数 → 余数不为0。

Part 3. CRC漏检概率的证明

CRC 漏检概率的核心,其完整表述是:当错误多项式 E ( x ) E(x) E(x) 是生成多项式 G ( x ) G(x) G(x) 的倍数时,CRC 会发生漏检,且在随机错误模型下,漏检的概率约为 1 / 2 r 1/2^r 1/2r r r r 是生成多项式 G ( x ) G(x) G(x) 的阶数,即 CRC 校验码的长度)。

下面我们从错误模型、多项式整除性、概率推导三个层面,严谨证明这个结论:

1. 前提:随机错误模型假设

漏检概率的计算基于一个合理的工程假设:

  • 数据在传输过程中,每个比特发生翻转的概率是独立的,且错误模式是随机分布的。
  • 错误多项式 E ( x ) E(x) E(x) 的每一项系数(对应比特是否翻转)是 0 或 1 的随机变量,所有可能的 E ( x ) E(x) E(x) 出现的概率均等。

2. 漏检的充要条件

根据之前的 CRC 正确性证明,接收方计算的余数为:
Remainder [ T ′ ( x ) / G ( x ) ] = Remainder [ E ( x ) / G ( x ) ] \text{Remainder}[T'(x)/G(x)] = \text{Remainder}[E(x)/G(x)] Remainder[T(x)/G(x)]=Remainder[E(x)/G(x)]
漏检发生的充要条件是:
Remainder [ E ( x ) / G ( x ) ] = 0 \text{Remainder}[E(x)/G(x)] = 0 Remainder[E(x)/G(x)]=0
等价于:
E ( x ) = K ( x ) ⋅ G ( x ) E(x) = K(x) \cdot G(x) E(x)=K(x)G(x)
其中 K ( x ) K(x) K(x) 是任意非零多项式。也就是说,只有当错误模式恰好对应 G ( x ) G(x) G(x) 的某个倍数时,才会漏检

3. 概率推导:为什么漏检概率是 1 / 2 r 1/2^r 1/2r

我们可以从余数空间的大小错误多项式的分布两个角度分析:

  1. 余数空间的大小
    对于阶数为 r r r 的生成多项式 G ( x ) G(x) G(x),任何多项式除以 G ( x ) G(x) G(x) 得到的余数 R ( x ) R(x) R(x) 满足:
    deg ( R ( x ) ) < r \text{deg}(R(x)) < r deg(R(x))<r
    因此余数 R ( x ) R(x) R(x) 对应的二进制序列长度为 r r r 位,总共有 2 r 2^r 2r 种可能的余数(从 000 ⋯ 0 000\cdots0 0000 111 ⋯ 1 111\cdots1 1111)。

  2. 随机错误下的余数分布
    在随机错误模型中,错误多项式 E ( x ) E(x) E(x) 是完全随机的,因此它除以 G ( x ) G(x) G(x) 得到的余数也是均匀分布 2 r 2^r 2r 种可能中的。

    • 余数为 0 0 0 的情况,恰好对应漏检场景,仅占 1 1 1 种。
    • 其余 2 r − 1 2^r-1 2r1 种余数均会被检测到。
  3. 最终概率计算
    漏检概率 = (余数为 0 的情况数) / (总余数情况数) = 1 2 r \frac{1}{2^r} 2r1

4. 关键补充:为什么实际漏检概率极低

  • 对于 CRC-32( r = 32 r=32 r=32),漏检概率为 1 / 2 32 ≈ 2.3 × 1 0 − 10 1/2^{32} \approx 2.3 \times 10^{-10} 1/2322.3×1010,这是一个几乎可以忽略的极小值。
  • 工程中选择的生成多项式(如 CRC-32 标准多项式)还会额外满足一些性质(比如包含因子 x + 1 x+1 x+1),可以进一步排除特定类型的错误(如奇数个比特错误),让实际漏检概率比理论值更低。

总结

CRC 漏检的本质是错误多项式恰好是生成多项式的倍数,在随机错误模型下,由于余数均匀分布在 2 r 2^r 2r 种可能中,因此漏检概率为 1 / 2 r 1/2^r 1/2r,且 r r r 越大(校验码越长),漏检概率越低。


Part 4. CRC-16 的C语言实现

以下是 CRC-16(标准多项式:0x8005,对应 x 16 + x 15 + x 2 + 1 x^{16}+x^{15}+x^2+1 x16+x15+x2+1)的C语言实现,包含「逐位计算法」和「查表优化法」两种核心方式(前者直观易懂,后者效率更高),并附带详细注释和测试用例,帮助理解CRC的计算过程。

一、CRC-16 核心参数说明

  • 生成多项式: G ( x ) = x 16 + x 15 + x 2 + 1 G(x) = x^{16} + x^{15} + x^2 + 1 G(x)=x16+x15+x2+1 → 二进制 1000000000000101 → 十六进制 0x8005
  • 校验码长度: r = 16 r=16 r=16 位(2字节)
  • 初始值:0xFFFF(常见约定,也可根据协议调整为 0x0000
  • 异或输出:0xFFFF(最终结果需与该值异或,部分协议可能为 0x0000
  • 运算规则:高位优先(MSB First)

二、实现代码(含两种方法+测试用例)

#include <stdint.h>
#include <stdio.h>
#include <string.h>

// -------------------------- 方法1:逐位计算法(直观易懂,适合理解原理)--------------------------
/**
 * @brief  CRC-16 逐位计算(高位优先)
 * @param  data: 待校验的原始数据
 * @param  len:  原始数据长度(字节数)
 * @return 16位CRC校验码(uint16_t)
 */
uint16_t crc16_bitwise(const uint8_t *data, uint32_t len) {
    const uint16_t poly = 0x8005;  // 生成多项式 G(x) = x^16 + x^15 + x^2 + 1
    uint16_t crc = 0xFFFF;         // 初始值(约定值)

    // 1. 遍历每一个字节(原始数据的所有字节)
    for (uint32_t i = 0; i < len; i++) {
        // 2. 将当前字节与CRC的高8位异或(CRC共16位,高8位是 crc >> 8)
        crc ^= (uint16_t)(data[i] << 8);  // 左移8位,对齐CRC高8位

        // 3. 遍历当前字节的每一位(8位)
        for (uint8_t j = 0; j < 8; j++) {
            // 4. 判断CRC最高位是否为1:若为1,左移后异或多项式;若为0,仅左移
            if (crc & 0x8000) {  // 0x8000 是 16位的最高位(第15位)
                crc = (crc << 1) ^ poly;
            } else {
                crc <<= 1;  // 最高位为0,左移后无需异或
            }
        }
    }

    // 5. 最终结果与 0xFFFF 异或(约定输出处理)
    return crc ^ 0xFFFF;
}

// -------------------------- 方法2:查表优化法(效率更高,工程常用)--------------------------
// 步骤1:预生成CRC-16 查找表(256个值,对应0~255每个字节的CRC结果)
static uint16_t crc16_table[256] = {0};

/**
 * @brief  预生成CRC-16查找表(程序启动时调用1次即可)
 */
void crc16_init_table(void) {
    const uint16_t poly = 0x8005;
    // 遍历0~255所有可能的字节值
    for (uint16_t i = 0; i < 256; i++) {
        uint16_t crc = i << 8;  // 对齐16位CRC的高8位
        // 逐位计算当前字节的CRC值,存入表中
        for (uint8_t j = 0; j < 8; j++) {
            if (crc & 0x8000) {
                crc = (crc << 1) ^ poly;
            } else {
                crc <<= 1;
            }
        }
        crc16_table[i] = crc;
    }
}

/**
 * @brief  CRC-16 查表计算(高位优先,效率是逐位法的8倍)
 * @param  data: 待校验的原始数据
 * @param  len:  原始数据长度(字节数)
 * @return 16位CRC校验码(uint16_t)
 */
uint16_t crc16_table_lookup(const uint8_t *data, uint32_t len) {
    uint16_t crc = 0xFFFF;  // 初始值

    for (uint32_t i = 0; i < len; i++) {
        // 核心:用当前字节与CRC高8位异或,作为查表索引,再更新CRC
        crc = (crc << 8) ^ crc16_table[(crc >> 8) ^ data[i]];
    }

    return crc ^ 0xFFFF;  // 最终异或输出
}

// -------------------------- 测试用例 --------------------------
int main(void) {
    // 测试数据1:"123456789"(CRC-16标准测试数据,预期结果:0xBB3D)
    const uint8_t test_data1[] = "123456789";
    uint32_t len1 = strlen((const char *)test_data1);

    // 测试数据2:自定义数据(如0x01, 0x02, 0x03),可自行验证
    const uint8_t test_data2[] = {0x01, 0x02, 0x03, 0x04, 0x05};
    uint32_t len2 = sizeof(test_data2) / sizeof(test_data2[0]);

    // 初始化查找表(仅需1次)
    crc16_init_table();

    // 方法1:逐位计算测试
    uint16_t crc1 = crc16_bitwise(test_data1, len1);
    uint16_t crc3 = crc16_bitwise(test_data2, len2);

    // 方法2:查表计算测试
    uint16_t crc2 = crc16_table_lookup(test_data1, len1);
    uint16_t crc4 = crc16_table_lookup(test_data2, len2);

    // 输出结果
    printf("=== CRC-16 测试结果 ===\n");
    printf("测试数据1:%s\n", test_data1);
    printf("逐位计算结果:0x%04X(预期:0xBB3D)\n", crc1);
    printf("查表计算结果:0x%04X(预期:0xBB3D)\n\n", crc2);

    printf("测试数据2:0x01, 0x02, 0x03, 0x04, 0x05\n");
    printf("逐位计算结果:0x%04X\n", crc3);
    printf("查表计算结果:0x%04X\n", crc4);

    return 0;
}

三、代码核心逻辑解释(对应CRC原理)

1. 逐位计算法(重点理解)

完全对应之前讲的「多项式模2除法」,每一步都能映射到代数运算:

  • 初始值 0xFFFF:相当于模2除法的「初始余数」(约定值,可调整)。
  • crc ^= (data[i] << 8):将当前字节(8位)与CRC的高8位异或,对应「多项式相加」(模2运算)。
  • 判断最高位 crc & 0x8000:对应模2除法中「除数(生成多项式)与被除数最高位对齐」,若被除数最高位为1,则减去除数(异或多项式)。
  • 左移操作 crc << 1:对应模2除法的「被除数右移一位」(等价于多项式乘以 x x x)。
  • 最终异或 0xFFFF:是CRC的约定输出处理,目的是避免全0数据的CRC结果为0(可选,部分协议无此步骤)。
2. 查表优化法(工程实用)
  • 核心思想:预先生成「0~255每个字节对应的CRC中间结果」(存在crc16_table中),计算时直接查表,无需逐位循环,效率提升8倍(因为每个字节少了8次位运算)。
  • 查表公式 crc = (crc << 8) ^ crc16_table[(crc >> 8) ^ data[i]]
    1. crc << 8:CRC左移8位,腾出低8位空间。
    2. (crc >> 8) ^ data[i]:用CRC的高8位与当前字节异或,得到查表索引(0~255)。
    3. 异或查表结果:快速得到当前字节的CRC贡献值,更新CRC。

四、测试结果验证

编译运行代码后,输出应满足:

  • 标准测试数据 "123456789" 的CRC-16结果固定为 0xBB3D(行业通用验证值),说明代码正确。
  • 逐位法和查表法结果完全一致,证明两种实现等价。

五、灵活调整(适配不同协议)

如果需要适配其他CRC-16变种(如Modbus-RTU、CCITT),只需修改3个参数:

协议生成多项式初始值异或输出
标准CRC-160x80050xFFFF0xFFFF
Modbus-RTU0x80050xFFFF0x0000
CRC-16-CCITT0x10210x00000x0000

例如,若要实现Modbus-RTU的CRC-16,只需将代码中 return crc ^ 0xFFFF 改为 return crc ^ 0x0000 即可。

通过这段代码,可以直观看到:CRC的计算本质是「基于约定规则的位运算循环」,完全遵循多项式模2除法的代数逻辑。

### CRC校验的数学理论基础 CRC(循环冗余校验)是一种用于检测数据传输错误的技术,其核心在于利用多项式除法来计算校验码。具体来说,在进行CRC运算时,首先将待处理的数据视为一个巨大的二进制数[^1]。 #### 多项式表示方法 为了便于理解和操作,CRC采用了一种特殊的数学工具——多项式。这里所说的多项式并非传统意义上的代数表达式,而是指一种特定形式的二元多项式,仅含有两个系数0和1。对于任意给定的消息序列M(x),可以找到一个最高幂次不超过r的最大公因式G(x),作为生成多项式[^3]。 #### 模2除法规则 值得注意的是,这里的加减乘除均遵循模2原则执行,这意味着所有的运算都不涉及任何进位或借位的概念。例如,当遇到相同位置上的两位相同时,则它们相互抵消;反之则保留一位不变。这种特性使得整个过程更加简单高效。 #### 计算流程概述 在实际应用过程中,发送端会先根据选定好的生成多项式G(x)对原始消息P(x)做一次完整的除法得到商Q(x)以及剩余R(x)[^4]。随后,将此余数值附加到原信息后面形成最终传输格式T(x)=P(x)*x^r+R(x)。接收者收到之后重复上述步骤验证所得结果是否一致即可确认通信质量良好与否。 ```python def crc_remainder(input_bitstring, polynomial_bitstring, initial_filler): len_input = len(input_bitstring) initial_padding = initial_filler * (len(polynomial_bitstring) - 1) input_padded_array = list(input_bitstring + initial_padding) while '1' in input_padded_array[:len_input]: cur_shift = input_padded_array.index('1') for i in range(len(polynomial_bitstring)): input_padded_array[cur_shift + i] = str(int(polynomial_bitstring[i] != input_padded_array[cur_shift + i])) return ''.join(input_padded_array)[len_input:] print(crc_remainder("11010011101100", "1011", '0')) # 输出crc校验后的余数 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颹蕭蕭

白嫖?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值