CRC(Cyclic Redundancy Check) 循环冗余校核

news2024/11/15 21:23:34

最近准备开始更新一个算法系列,这个系列嘛就是别管有没有用先学为敬系列(或者现学现卖系列)。那么这个系列的第一篇就用我这两天看的CRC算法当作开篇吧。

1)什么是CRC呢?

如百度所诉,好像是一个十分有用的算法,下为百度内容

CRC(Cyclic Redundancy Check),即循环冗余校核,是一种根据网络数据包或电脑文件等数据产生简短固定位数校核码的快速算法,主要用来检测或校核数据传输或者保存后可能出现的错误。CRC利用除法及余数的原理,实现错误侦测的功能,具有原理清晰、实现简单等优点。

2)CRC原理是什么?

先需要了解一个概念,叫做二进制除法,这里我看了很多资料。我的理解并不是除法,而是一种将一串较长的二进制数据从高位开始对一个较短的二进制数据位异或,得到的结果如果高位为0则左移这个较长数据继续位异或,直到移动到最低位以后,则最终的异或结果为余数。我想之所以被叫做除法是因为和除法的规律一致,有被除数,商和余数。

下面贴两张我写算法过程中计算的两张图,也会和后面的源代码对应

crc 就是利用这个二进制除法的公式去进行校验的。首先找一个公共的被除数,然后将原始数据左移这个被除数的长度在末尾补0当除数,然后用二进制除法计算出余数,再将余数加到除数上。得出的结果作为数据传输。这样在做数据校验的时候,只需要将这个结果除以之前的被除数,如果没有余数就说明数据传输过程没有丢失。这个原理我自己思考了一下,为什么要在末尾补0的问题。我想主要是不影响原始数据吧。因为这样得到的余数正好可以加到原始数据的后八位。而在后续进行校验的时候不需要再对数据做任何处理,因为用来计算的数据就是 ,高8位数原始数据,低八位是计算后得到的余数,校验的数据直接使用传输数据即可。(这里不一定是低8位,位之所以用8位当作被除数的长度,是因为8位正好一个字节计算起来更简单,不用做一些位移操作)。或者反过来想,如果不做位移那么得到的余数会受到原始数据长度的影响,会让算法写起来更加复杂。

下面就是我用c++写的算法,由于我还是一个c++的初学者,所以写的可能不太好。但输出结果是对的,是符合crc算法原理的。打印二进制的方法是参照了别人的代码进行修改的,只是为了方便查看结果是否正确。整段代码是可以直接运行的,运行结果放在下面。

以上就是我努力了一天才写好的crc。最开始真的是卡在了原理,然后今天早上看到一个博主写的非常明白的原理,才有了这篇博客。推荐一下这篇博客

CRC校验原理及步骤_erci_fc2336的博客-CSDN博客_crc校验

需要注意c++右移会带着符号位,因此右移需要使用无符号类型

#include "stdio.h"
#include "stdlib.h"
#include "iostream"
using namespace std;
// 代码格式化 option+shift+f

int16_t testCrc(int8_t data);
int16_t checkCrc(int16_t data);
int main()
{
   int8_t data = 0b10001010;
   int16_t result = testCrc(data);
   checkCrc(result);
   return 0;
}

void print16binry(int16_t num)
{
   int count = (sizeof(num) << 3) - 1;
   while (count >= 0)
   {
      int16_t bitnum = num >> count;
      int16_t byte = bitnum & 1;
      printf("%d", byte);

      // if (count%4==0) {
      if (count % 8 == 0)
      {
         printf(" ");
      }

      count--;
   }
   printf("\n");
}
void print8binry(int8_t num)
{
   int count = (sizeof(num) << 3) - 1;
   while (count >= 0)
   {
      int8_t bitnum = num >> count;
      int8_t byte = bitnum & 1;
      printf("%d", byte);

      // if (count%4==0) {
      if (count % 8 == 0)
      {
         printf(" ");
      }

      count--;
   }
   printf("\n");
}
void printUnsighedBinry(unsigned int num)
{
   int count = (sizeof(num) << 3) - 1;
   while (count >= 0)
   {
      unsigned int bitnum = num >> count;
      unsigned int byte = bitnum & 1;
      printf("%d", byte);

      // if (count%4==0) {
      if (count % 8 == 0)
      {
         printf(" ");
      }

      count--;
   }
   printf("\n");
}

int16_t testCrc(int8_t data)
{
   int16_t result = 0;           // 结果
   int8_t dividend = 0b10010101; // 被除数
   int16_t wdata = data << 8;    // 讲数据左移到高8位
   printf("wdata:");
   print16binry(wdata);
   unsigned int divisor = data << 8;
   // int16_t divisor = 0b0 | data;
   // printf("divisor:");
   // printbinry(divisor);
   int bit = 8; // 位移的位数
   
   int8_t temp = 0;
   temp = divisor >> bit;
   int8_t moveCount = 0;
   for (int i = bit; i > 0; i--)
   {

      printf("temp:");
      print8binry(temp);
      temp = temp ^ dividend;
      printf("temp2:");
      print8binry(temp);
      int8_t high0 = 0; // 异或结果的高位0
      for (int i = 7; i > 0; i--)
      {
         if ((temp >> i) > 0)
         {
            break;
         }
         else
         {
            moveCount++;
            high0++;
            if (moveCount == 8)
            {
               break;
            }
         }
      };
      temp = temp << high0;
      if (moveCount == 8)
      {
         break;
      }
   };
   unsigned int unsingedTemp=temp;
   unsingedTemp= unsingedTemp<<24;
   unsingedTemp= unsingedTemp>>24;
   result = wdata | unsingedTemp;
   printf("result:");
   printUnsighedBinry(unsingedTemp);
   print16binry(result);
   printf("\n");
   return result;
}

int16_t checkCrc(int16_t data)
{
   int16_t result = 0;
   int8_t dividend = 0b10010101;
   int8_t completeTemp = data;
   unsigned int completeW = completeTemp;//使用无符号int 
   printf("init completeW:"); 
   printUnsighedBinry(completeW);
   printf("data:");
   print16binry(data);
   int16_t divisor = data;
   // int16_t divisor = 0b0 | data;
   // printf("divisor:");
   // printbinry(divisor);
   // int16_t divisor = 0b0 | data;
   // printf("divisor:");
   // printbinry(divisor);
   int bit = 8; // 位移的位数

   int8_t temp = 0;
   temp = divisor >> bit; // 从高8位开始
   int8_t moveCount = 0;
   int8_t high0 = 0;
   for (int i = bit; i > 0; i--)
   {

      printf("temp:");
      print8binry(temp);
      temp = temp ^ dividend;
      printf("temp2:");
      print8binry(temp);
      completeW = completeW<<24;
      completeW = completeW<<high0;
      completeW = completeW>>24;//这里之所以移来移去是需要使用低八位。无符号的int似乎只有 32位的
      printf("completeW:"); 
      printUnsighedBinry(completeW);

      printUnsighedBinry(completeW);
      high0 = 0; // 异或结果的高位0
      for (int i = 7; i > 0; i--)
      {
         if ((temp >> i) > 0)
         {
            break;
         }
         else
         {
            moveCount++;
            high0++;
            if (moveCount == 8)
            {
               break;
            }
         }
      };

      // print16binry(completeW);
      int16_t tempw = temp << 8; // 左移以后使用数据的后8位补充
      printf("tempw1:");
      print16binry(tempw);
      tempw = tempw | completeW;
      printf("tempw:");
      print16binry(tempw);
      tempw = tempw << high0;
      temp = tempw >> 8; // 保留8位进行计算
      if (moveCount == 8)
      {
         break;
      }
   };
   printf("result:");
   print8binry(temp);
   printf("\n");
   return result;
}

​​​​​​​

 

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

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

相关文章

pandas学习笔记(1)

学习网址&#xff1a;kaggle 注&#xff1a;本文仅为个人总结&#xff0c;不作为任何学习资料 一、在pandas里有两种Core objects&#xff1a;DataFrame和Series DataFrame的使用方法&#xff1a; DataFrame有两个方向&#xff0c;纵向为index,横向为column 定义一个DataFrame的…

vue3 antd项目实战——Form表单提交和校验【v-model双向绑定input输入框、form表单数据】

vue3 ant design vue项目实战——Form表单【v-model双向绑定数据实现form表单数据的提交】上期文章回顾【UI界面渲染】场景复现&#xff08;源代码附在文章最后&#xff09;实现需求1.表单数据及其类型的定义2.表单及各部分数据的双向绑定3.表单提交功能4.校验输入内容不为空5.…

计算机组成原理实训报告(附电路图)

实训一&#xff1a;运算器组成实验 目的要求&#xff1a; 掌握FA全加器的工作原理掌握行波进位的补码加法/减法器的工作原理了解ALU运算器的工作原理 掌握FA全加器的工作原理&#xff1a; 实验步骤&#xff1a;创建一个叫做FA的电路&#xff0c;然后开始绘制。 放一个或门&a…

记一次内网渗透过程学习|天磊卫士

一、靶场说明 此靶场共有3台主机 Win7为双网卡&#xff0c;桥接为模拟外网ip&#xff08;192.168.1.220&#xff09;&#xff0c;nat&#xff08;192.168.52.142&#xff09;模拟内网域环境&#xff0c;处于DMZ区域的web服务器 Win2013为内网域控成员&#xff08;nat&#xff…

[综][PDPTW]A survey on pickup and delivery problems

相关数据集的下载:https://www.sintef.no/projectweb/top/pdptw/100-customers/ 由于Li&Lim生成测试实例的方式&#xff0c;这些实例中的任务数量不同&#xff0c;略高于标称值。 在这里&#xff0c;您可以找到Li&Lim的PDPTW基准问题的100个任务实例的实例定义和最著名…

哗啦啦疑似暴雷之后,平台老板们开始迫切寻求二清合规监管办法

&#xff08;图源百度后台&#xff0c;侵删&#xff09; 最近一则“哗啦啦资金链断裂 导致餐饮店无法提现”的帖子在餐饮人中疯传&#xff0c;引起了业内不小的轰动。据很多餐饮商户反馈&#xff0c;近一个多月以来&#xff0c;哗啦啦系统一直延期提现&#xff0c;网上舆论迅速…

微服务门神-Gateway路由

引言 书接上篇微服务门神-网关了解&#xff0c;讲完了解Gateway基本概念之后&#xff0c;本篇来看下Gateway路由实现 项目集成 还是延续之前例子&#xff1a;订单服务与商品服务 步骤1&#xff1a;创建一个 shop-gateway 的模块,导入相关依赖 <?xml version"1.0…

2022年年度总结

目录 一&#xff0c;回望我的2022 二&#xff0c;2023目标 一&#xff0c;回望我的2022 刚刚度过我迷茫的大一生活&#xff0c;我的大二生活也已经过去了一半。说实话&#xff0c;家里就我一个大学生&#xff0c;我实在是不知道怎么去面对我的大学生活&#xff0c;或者说我…

高性能web网关Openresty实践

高性能web网关之openresty一、openresty 简介二、openresty 安装三、openresty开发实践 —— content_by_lua 阶段四、openresty开发实践 —— rewrite_by_lua 阶段五、openresty开发实践 —— body_filter_by_lua 阶段六、openresty开发实践 —— 黑名单6.1、基础版6.2、进阶版…

【面试题】面试官:为什么Promise中的错误不能被try/catch?

大厂面试题分享 面试题库 前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 前言 之前我写过一篇文章&#xff0c;讨论了为什么async await中的错误可以被try catch&#xff0c;而setTimeout等api不能&#xff0c…

【pandas】教程:7-调整表格数据的布局

Pandas 调整表格的布局 本节使用的数据为 data/titanic.csv&#xff0c;链接为 pandas案例和教程所使用的数据-机器学习文档类资源-CSDN文库 导入数据 import pandas as pd titanic pd.read_csv("data/titanic.csv") titanic.head()PassengerId Survived Pclas…

传感器工作原理以及传感器种类详解

随着物联网时代的到来&#xff0c;现代信息技术快速发展&#xff0c;其中包含了计算机技术、通信技术和传感器技术等&#xff0c;计算机相当于人类的大脑&#xff0c;通信技术类似人体的神经&#xff0c;而传感器就等同于人的感觉器官。从广义上说&#xff0c;传感器就是一种能…

存储控制器

存储控制器是按照一定的时序规则对存储器的访问进行必要控制的设备&#xff0c;包括地址信号、数据信号以及各种命令信号的控制&#xff0c;使主设备(访问存储器的设备)能够根据自己的要求使用存储器上的存储资源。 存储控制器的作用主要就是进行接口的转换&#xff0c;将主设…

通信原理 | 一些常用的概念记录

这篇文章只是记录平时了解到的一些概念,并没有针对性,比较杂乱,纯粹就是当做笔记本用的,各位看官请在茶余饭后的休闲时间阅读最为合适了解到新的概念的话,会随时更新世界四大导航系统 世界上有四大卫星导航系统,它们分别是美国的GPS、俄罗斯的格洛纳斯卫星导航系统、欧盟…

尚医通-SpringBoot整合MongoDB(十七)

目录&#xff1a; &#xff08;1&#xff09;MongDB-SpringBoot整合-MongoTemplate操作 &#xff08;2&#xff09;MongoTemplate操作2 &#xff08;3&#xff09;MongoTemplate操作3 &#xff08;4&#xff09;MongoDB-SpringBoot整合-MongoRepository操作 &#xff08;1&a…

FIIL、南卡、漫步者蓝牙耳机怎么选?国产半入耳蓝牙耳机推荐

随着 TWS耳机市场的发展&#xff0c;越来越多的手机厂商&#xff0c;新晋的品牌&#xff0c;甚至是老牌的音频品牌都加入到了 TWS耳机的行列中&#xff0c;让消费者的选择范围变得更大。当前热销的南卡小音舱、漫步者Lolli3、FIIL CC2蓝牙耳机都是目前受消费者欢迎的&#xff0…

pyqt 显示图片的若干方法

date: 2022-11-30 14:23 status: public title: ‘pyqt 显示图片的若干方法’ 单张图片 使用lable 显示图片 特点是最简单&#xff0c;但功能也最少。 #!/usr/bin/env python # -*- coding: utf-8 -*- import sysfrom PyQt5.QtGui import QPixmap from PyQt5.QtWidgets impor…

JAVAGUI编程初识之AWT

文章目录前言一 GUI编程简介二 AWT简介2.1 组件(Component)和容器(Container)2.2 Frame2.2.1 演示1-创建一个窗口2.2.2 演示2-多个窗口的创建2.3 Panel2.3.1 演示-Panel使用三 布局管理3.1 布局管理器之FlowLayout3.1.1 FlowLayout简介3.1.2 演示-FlowLayout使用3.2 布局管理器…

电子签章结构以及规范讲解

前言&#xff1a; 安全电子签章是通过采用PKI公钥密码技术&#xff0c;将数字图像处理技术与电子签名技术进行结合&#xff0c;以电子形式对加盖印章图像数据的电子文档进行数字签名&#xff0c;以确保文档来源的真实性以及文档的完整性&#xff0c;防止对文档未经授权的篡改&…

算法训练 —— 链表(1)

目录 1. LeetCode203.移除链表元素 2. LeetCode21.合并两个有序链表 3. LeetCode206.翻转链表 4. LeetCode707.设计链表 1. LeetCode203.移除链表元素 移除链表元素 题解&#xff1a;通过两个指针来控制&#xff0c;cur和prev&#xff1b;cur指针去找val&#xff0c;prev…