是否可以使用 CRC 进行基本的纠错?
Posted
技术标签:
【中文标题】是否可以使用 CRC 进行基本的纠错?【英文标题】:Is it possible to do rudimentary error correction with CRC? 【发布时间】:2011-04-16 20:35:15 【问题描述】:我知道使用 CRC 的全部目的是进行错误检测,但我听说有人说除了错误检测之外,它还可以用来进行基本的错误纠正。我很好奇是不是这样,如果是这样,它有多强大?我的意思是,我们通常将 CRC 称为能够执行 x 位检测,但我很好奇它是否能够执行 x 位校正。如果是这样,这是如何工作的?谢谢。
【问题讨论】:
【参考方案1】:迟到的答案,但 CRC32 多项式
0x1f1922815 (= 0x787 * 0x557 * 0x465 * 0x3 * 0x3)
对于 1024 位(992 位数据,32 位 CRC)消息,最多可以检测 7 位错误并纠正最多 3 位错误。有 comb(1024,1) + comb(1024,2) + comb(1024,3) = 178957824 个可纠正的误码模式。如果有足够的内存用于 1431662592 字节表 (178957824*8 = ~1.4 GB),则可以生成所有可能的 1、2 和 3 位错误 CRC 并将其存储在该表中,其中每个条目将是:32 位 CRC 、一个 2 位错误计数和三个 10 位字段用于位错误位置。
然后将对该表进行排序,并且在检查 CRC 时,如果它是错误的,则对该表的二进制搜索(最多 28 个循环)可以确定它是 1、2 还是 3 位错误情况,并使用以下方法进行纠正存储在表中的索引。
但是,有 5 位或更多位错误的错误纠正的可能性。如果某些 5 位错误位模式产生与 3 位错误位模式相同的 CRC,则错误的 3 位将被更改,从而导致看似具有有效 CRC 的 8 位错误。
示例代码链接:
https://github.com/jeffareid/misc/blob/master/crccor3.c
【讨论】:
【参考方案2】:您可以使用 CRC 进行多位纠错。查看***,参考 koopmans 的工作,CRC 可以检测到其 hamming_distance-1 错误。汉明距离取决于有效载荷长度和使用的 CRC 多项式。因此,例如 0xBA0DC66B 的 Koopmans 多项式可以在长达 16360 位的消息中检测到多达 5 位的错误。前两条消息中描述的算法可以根据需要扩展到任意多的位,但时间随着要修复的位数呈指数增长。
-
计算错误 CRC = CRC_gotten ^ CRC_expected。
查看所有可能的 1 位消息(即全 0、1 和全 0)(需要评估 message_length 情况。注意这是 BITS 而不是 BYTES),错误位是生成错误 CRC 的消息。
反转检测到的位以纠正错误。
如果您找不到与错误 CRC 匹配的 1 位,请查看所有 2 位、3 位直到您的 hamming_distance-1。请注意,这会变慢变快,message_length 平方为 2 位,三次方为 3 位,最高为 5 位的五次方。
【讨论】:
所示算法的措辞似乎是单比特错误的 n 平方,两位错误的 n 立方等,因为它独立计算每个消息的 CRC 需要时间 N . 建议如何在没有 N 的额外因素的情况下完成它可能会有所帮助。 不,N 表示单个位。我可以在 logN 时间内计算 N 位中设置的单个位的 CRC。更好的是,给定 N 位消息中位置 X 的单个位的 CRC,我可以简单地告诉您位为 N+1 的消息的 CRC。这只是 CRC 内循环的一个步骤。 只是你的crc_forward函数循环:从1开始,crc_forward,是crc错误吗?不,crc_froward 并再次检查。 这有点误导……仅仅因为您可以检测 5 个单比特错误,并不意味着您也可以纠正它们。在实践中,对于您给定大小的消息,只能(通常)纠正 2 个单比特错误 - 这仅遵循鸽巢原理(长度为 16360 的消息中平均有 1000 多种可能出现 3 比特错误产生一个给定的CRC)。当然,单个突发错误是完全不同的情况 - 在这种情况下,除了生成多项式之外,所有 33位突发都可以被检测到,并且对于 10b。 @Arne,koopsmans 的工作包括一个表格,告诉您数据长度在哪里错误 CRC 停止对于给定位数的唯一性。只要您的消息比这短,错误代码将是唯一的。这当然取决于所使用的多项式。【参考方案3】:我最近从事 CRC16 错误检测和单位错误校正。
这是基本的想法:
-
假设您有一个位错误。
如果data+crc没有错误,则CRC为0,否则为0。
我们将发送的 CRC 定义为 CRC,将接收的 CRC 定义为 CRCr。
那么错误位由
CRCox = CRCs ^ CRCr
给出。
结果包含 CRC 错误和数据错误。
看看CRCox和误码是什么关系。
这清楚吗?我有一篇关于这个的论文。如果您想了解更多信息,请告诉我。
【讨论】:
我认为这可能是@Wandy所指的论文:espace.library.uq.edu.au/… 对于第 2 点,不是 CRC 为 0。而是接收到的 CRC 与根据接收到的数据计算的 CRC 进行异或运算! @Étienne 当然他的意思是接收到的数据+crc 的 CRC 将为零【参考方案4】:可以使用 CRC 进行单比特纠错。假设有一个 CRC“寄存器”,并且具有一次向前和向后运行 CRC 算法的函数,忽略传入的数据
int crc_forward(int old_value,int data_bit) 如果(旧值和 0x8000) 返回 ((old_value ^ 0x8000) SHL 1) ^ 0x1021 ^ data_bit; 别的 返回(旧值 SHL 1)^ 数据位; int crc_reverse(int old_value) 如果(旧值和 1) 返回(旧值 SHR 1)^ 0x8810; 别的 返回旧值 SHR 1;假设一个数据包经过计算,以便将 crc 初始化为某个值并为每个位(MSB 优先)运行 crc_forward 应该产生零。如果获得的 CRC 值不是零,则可以反向运行算法(忽略数据位),直到计算出的 CRC 值为 1。这就是错误位的位置。
请注意,这种方法可能适用于 NAND 闪存等软件纠错。为了有效地将其用于硬件纠错,必须能够延迟读取操作直到可以处理 ECC,或者需要一个“综合症”值和位位置表。
【讨论】:
也可以实现单突发校正。一些 16 位 CRC 多项式允许对最多 184 位的消息中的 7 位单次突发进行校正。以上是关于是否可以使用 CRC 进行基本的纠错?的主要内容,如果未能解决你的问题,请参考以下文章