常用的简单校验算法:校验和,异或校验,crc校验,LRC校验,补码求和,checksum

2023-05-16

常用的简单校验算法:校验和,异或校验,crc校验,LRC校验,补码求和,checksum

相关思路和源码来自网络,自己只是整理, 做笔记用。

并未完整完善正确归纳,只是个人理解初步做笔记记录。

在实现业务需求过程中,通常要用到相关一些校验算法,简单整理常用校验算法并做笔记:

常用校验算法简单说明:

1:校验和:按每个字节,计算累加和,

2:异或校验:定义初值,按每个字节异或,求结果。

3:CRC校验:已有很多的标准及计算方式,可以返回8字节,16字节,32字节的结果。

受益匪浅的文章:https://blog.csdn.net/u013073067/article/details/86621770

​ 设置crc值和多项式码;依次遍历每个字节,与crc值进行异或;crc值取出最低位的值,并右移一位;如果最低位值位1,则于多项式码进行异或;循环直到8位结束。

crc查表思想:观察,内部有个循环,每次对一个字节(8位)的循环中,对crc码的数字是不变的,这里与多项式码相关,可以直接用数组代替这里的求值。(crc表与crc返回8/16/32位有关,与多项式码有关)

4:LRC校验:是不可靠的,先求和,再对结果取反+1

5:checksum:对checksum值归0,每16bit求和,不够16bit的高位补0,如果checksum溢出,则高16bit和低16bit相加进行处理(依次循环判断)。

测试demo:

//实现对原数据进行checksum计算校验测试demo
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
//校验和  返回一个字节
unsigned char Check(const unsigned char *buf, int len)  
{  
    int iSum = 0; 
    for (int i = 0;i < len;i++)  
    {  
        iSum += buf[i];  
    }  
    iSum %= 0x100;   //也可以&0xff
    return (unsigned char)iSum;  
} 

//异或校验 返回一个字节
unsigned char CheckXor(const char *strData,int len)  
{  
    char checksum = 0;  
    for (int i = 0;i < len;i++)  
    {  
        checksum = checksum ^ strData[i];  
    }  
    return (unsigned char)checksum;  
}  

//电子通信领域非常常用,已经有一些特定的计算方式
//CRC校验 (返回两个字节 高字节在前,低字节在后)  循环冗余校验
unsigned short int CRC(const unsigned char *buf, int leng)  
{  
    unsigned short int  Reg,temp,Crccode,i,j;  
    Reg = 0xFFFF;  					//设置crc的值    FF FF
    Crccode = 0xA001;     			//定义的一个多项式码,最终都会与这个码异或
    for ( i=0;i<leng;i++ )  
    {     
        Reg ^= *(buf+i);  			//进行异或  与crc的低8位
        	// ==》注意这里的循环 其实都是固定的值,可以直接计算生成一个表来直接获取
        for ( j=0;j<8;j++ )  
        {     
            temp=Reg&0x0001;      	//获取当前最低位的数字
            Reg=Reg>>1;  			//向右移一位
            if( temp==0x0001 )   	//判断移出的最低位的值,如果为1,则与上文定义的多项式码进行异或,为0,则不处理
                Reg^=Crccode;   
        }   
    }  								//重复处理完所有的数据
    return (Reg<<8 | Reg>>8);   //(Reg^ 0xffff)   ==>这里其实做了反转
} 

// 纵向冗余校验 异或校验和 不可靠
//LRC校验 求和  取反  +1
unsigned char LRC(const unsigned char *auchMsg, unsigned short usDataLen)  
{  
    unsigned char uchLRC=0;  
    while(usDataLen--)  
    {  
        uchLRC+=*auchMsg++;  
    }  
    return ((unsigned char)(-((char)uchLRC)));  
} 


//补码求和
unsigned char Check1(const unsigned char *buf, int len)
{
    int iSum = 0;
    for (int i = 0;i < len;i++)
    {
      iSum += buf[i];
    }
    iSum = 256 - iSum;
   	return (unsigned char)iSum;
}

//把传入checksum置为0  每2个字节求和
//这里没有加入溢出情况  将高16bit和低16bit相加处理
uint32_t checksum(const void *buf, size_t len, uint32_t sum)
{
	/* workaround gcc strict-aliasing warning */
	uintptr_t ptr = (uintptr_t)buf;
	typedef uint16_t __attribute__((__may_alias__)) u16_p;
	const u16_p *u16_buf = (const u16_p *)ptr; //把数据按照2byte进行划分

	//减少循环次数而已
	while (len >= (sizeof(*u16_buf) * 4)) { //把2byte对应的值,依次累加到一个4byte值中
		sum += u16_buf[0];
		sum += u16_buf[1];
		sum += u16_buf[2];
		sum += u16_buf[3];
		len -= sizeof(*u16_buf) * 4;
		u16_buf += 4;
	}
	while (len >= sizeof(*u16_buf)) {	//把不够4位的,也加入sum中
		sum += *u16_buf;
		len -= sizeof(*u16_buf);
		u16_buf += 1;
	}

	/* if length is in odd bytes */
	if (len == 1)	//如果最后的数据不够2byte,其实就是当成2byte处理,高位补0
		sum += *((const uint8_t *)u16_buf);

	return sum;	//这里对最终的结果是如何处理的? 参考具体代码或者业务
}

int main(int argc, char* argv[])
{

	//校验和测试  返回一个字节
	const char * src_data = "abcdefghi";
	printf("check %02x \n", Check((const unsigned char*)src_data, strlen(src_data))); //check 8d 

	printf("CheckXor %02x  \n", CheckXor((const char*)src_data, strlen(src_data)));  //CheckXor 61 

	printf("CRC : %02x   \n", CRC((const unsigned char*)src_data, strlen(src_data)));	//CRC : 7f00 

	printf("LRC: : %02x   \n", LRC((const unsigned char*)src_data, strlen(src_data)));   //LRC: : 73

	printf("Check1: %02x   \n", Check1((const unsigned char*)src_data, strlen(src_data))); //Check1: 73 

	printf("sizeof(char*) = %lu \n", sizeof(char*));
	unsigned int cksum = checksum((const void*)src_data, strlen(src_data), 0); //checksum : 6a06
	cksum = (cksum == 0xffff) ? cksum : (uint16_t)~cksum;
	printf("checksum : %02x  \n", cksum);

//使用简单的异或的方案,进行简单的测试
	const char* data = "2|4|12312|119|{\"InternalFleetNum\":\"12345\",\"CoordX\":1178263,\"CoordY\":2083177,\"Heading\":121.7,\"LocationCode\":\"AVB\",\"RequestId\":1234567}";
	printf("data is [%s] \n",data);
	char* buff = NULL;
	buff = (char*)malloc(strlen(data) +2);
	memset(buff, 0, strlen(data) +2);
	memcpy(buff, data, strlen(data));
	printf("buff is [%s] \n",buff);
	unsigned char check_xor = CheckXor((const char*)data, strlen(data));
	printf("check_xor = [%c] \n", check_xor);
	memcpy(buff+strlen(data), (char*)&check_xor, 1);
	printf("buff adn check_xor is [%s] \n",buff);


	//试一下校验  收到的是buff  然后数据的总长度是 strlen(data)+1 
	unsigned char check_xor1 = CheckXor(buff, strlen(buff)-1);
	printf("check_xor1 is [%c] \n", check_xor1);
	// if(check_xor != (unsigned char)recv_buff+len-1)
	printf("data check_xor is [%c] \n", *(buff+strlen(buff)-1));
	if(check_xor1 == *(buff+strlen(buff)-1))
	{
		printf("data is success ! \n");
	}else
	{
		printf("data is error! \n");
	}
	return 0;
}


/***************************
check 8d 
CheckXor 61  
CRC : 7f00   
LRC: : 73   
Check1: 73   
sizeof(char*) = 8 
checksum : 6a06  
data is [2|4|12312|119|{"InternalFleetNum":"12345","CoordX":1178263,"CoordY":2083177,"Heading":121.7,"LocationCode":"AVB","RequestId":1234567}] 
buff is [2|4|12312|119|{"InternalFleetNum":"12345","CoordX":1178263,"CoordY":2083177,"Heading":121.7,"LocationCode":"AVB","RequestId":1234567}] 
check_xor = [S] 
buff adn check_xor is [2|4|12312|119|{"InternalFleetNum":"12345","CoordX":1178263,"CoordY":2083177,"Heading":121.7,"LocationCode":"AVB","RequestId":1234567}S] 
check_xor1 is [S] 
data check_xor is [S] 
data is success ! 
****************************/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

常用的简单校验算法:校验和,异或校验,crc校验,LRC校验,补码求和,checksum 的相关文章

  • mySQL(关系型数据库管理系统)编辑

    收藏 2906 1034 mySQL xff08 关系型数据库管理系统 xff09 编辑 MySQL 1 是一个 关系型数据库管理系统 xff0c 由瑞典 MySQL AB公司开发 xff0c 目前属于 Oracle公司 MySQL是最流行
  • CPU的核心数、线程数的关系和区别

    我们在选购电脑的时候 xff0c CPU是一个需要考虑到核心因素 xff0c 因为它决定了电脑的性能等级 CPU从早期的单核 xff0c 发展到现在的双核 xff0c 多核 CPU除了核心数之外 xff0c 还有线程数之说 xff0c 下面
  • STM32单片机,下载器下载完程序能正常跑起来,断电再上电程序不运行

    晶振坏了 转载于 https www cnblogs com god of death p 7050281 html
  • CUDA性能优化----warp深度解析

    CUDA性能优化 warp深度解析 2017 01 12 16 41 07 分类 xff1a HPC amp CUDA优化 标签 xff1a gpu cuda hpc 举报 字号 订阅 下载LOFTER 我的照片书 1 引言 CUDA性能优
  • 螺旋桨转矩

    xfeff xfeff 在螺旋桨气动力分析时 xff0c 首先应用翼型理论进行螺旋桨叶素分析 利用翼型升阻特性数据 xff0c 回避了有限机翼的展弦比问题 xff0c 诱导流动由涡流模型确定 xff0c 取决于桨叶数目 间距以及作用于每片桨
  • 给初学者们讲解人工神经网络(ANN)

    1 介绍 这份教学包是针对那些对人工神经网络 xff08 ANN xff09 没有接触过 基本上完全不懂的一批人做的一个简短入门级的介绍 我们首先简要的引入网络模型 xff0c 然后才开始讲解ANN的相关术语 作为一个应用的案例 xff0c
  • OpenMP基本概念

    OpenMP是一种用于共享内存并行系统的多线程程序设计方案 xff0c 支持的编程语言包括C C 43 43 和Fortran OpenMP提供了对并行算法的高层抽象描述 xff0c 特别适合在多核CPU机器上的并行程序设计 编译器根据程序
  • 散度和旋度的物理意义是什么?

    高等数学学的时间有点久远了 xff0c 最近需要推倒一些公式 xff0c 以前高数学的时候这公式那定理的都没说什么物理意义 xff0c 现在接触的问题都是具有一定物理意义的 xff0c 感觉对不上 xff0c 回来找找资料好好理解一下 xf
  • 格林公式、高斯公式及斯托克斯公式的理解及相互关系

    最近要推倒波动方程积分解 xff0c 要对散度 旋度以及他们之间的相互关系有一个理解 看了两天 xff0c 自己认为理解的差不多了 xff0c 现在写在这个地方 xff0c 作为笔记 xff0c 以后忘记了拿过来看一下 xff0c 加深一下
  • Radon变换理论介绍

    本人最近在研究Radon变换 xff0c 在查阅了各种资料之后在此写下个人的理解 xff0c 希望与各位牛牛进行交流共同进步 xff0c 也使得理解更加深刻些 Radon变换的本质是将原来的函数做了一个空间转换 xff0c 即 xff0c
  • test

    lt DOCTYPE html gt lt html lang 61 34 en 34 gt lt head gt lt meta charset 61 34 utf 8 34 gt lt meta http equiv 61 34 X U
  • BIT内存顺序

    机器的最小寻址单位是字节 xff0c bit无法寻址 xff0c 也就没有高低地址和起始地址的概念 xff0c 我们需要定义一下bit的 地址 以一个字节为例 xff0c 我们把从左到右的8个bit的位置 position 命名按顺序命名如
  • 无人驾驶感知篇之融合(五)

    今天早上看到上海新增一万七千左右 xff0c 看的真的很揪心 xff01 希望白衣战士能早点战胜这场疫情 xff0c 期待明天能有好消息 xff01 今天具体讲讲多贝叶斯估计算法的原理 xff0c 多贝叶斯估计法的主要思想是将传感器信息依据
  • MAC地址的介绍(单播、广播、组播、数据收发)

    MAC地址组成 网络设备的MAC地址是全球唯一的 MAC地址长度为48比特 xff0c 通常用十六进制表示 MAC地址包含两部分 xff1a 前24比特是组织唯一标识符 xff08 OUI xff0c OrganizationallyUni
  • stm32通用定时器输出PWM控制舵机

    stm32的通用定时器有TIM2 TIM3 TIM4 TIM5 xff0c 每个定时器都有独立的四个通道可以作为 xff1a 输入捕获 输出比较 PWM输出 单脉冲模式输出等 stm32除了基本定时器 xff0c 其他定时器都能输出PWM
  • Linux内核Socket CAN中文文档

    自己在年假中空闲之余翻译的内核中Socket CAN的文档 xff0c 原文地址在 xff1a http lxr linux no linux 43 v2 6 34 Documentation networking can txt 但是这篇
  • c/c++自定义通讯协议(TCP/UDP)

    前言 xff1a TCP与UDP是大家耳熟能详的两种传输层通信协议 xff0c 本质区别在于传输控制策略不相同 xff1a 使用TCP协议 xff0c 可以保证传输层数据包能够有序地被接受方接收到 xff0c 依赖其内部一系列复杂的机制 x
  • ubuntu 使用虚拟can 与 socketCAN使用

    原文链接 xff1a https blog csdn net xiandang8023 article details 127990159 创建虚拟CAN接口 在Linux上能使用虚拟CAN接口之前 xff0c 需要在终端执行以下三个步骤
  • cmake引入第三方库

    cmake引入第三方库 第三方库包含 lib文件和 h hpp文件动态库还包含 dll文件 小例程 3rdparty bin test dll include test hpp lib Debug test lib Release test
  • AHB-APB总线协议

    AHB APB总线协议 文章目录 AHB APB总线协议一 AHB APB总线介绍二 AHB总线设备1 AHB主设备 xff08 master xff09 2 AHB从设备 xff08 slave xff09 3 AHB仲裁器 xff08

随机推荐