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

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

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

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

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

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

常用校验算法简单说明:

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

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

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

设置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 ! 
****************************/
目录
相关文章
|
7月前
|
传感器 算法 数据格式
QT Modbus RTU调试助手(包含算法实现CRC MODBUS16校验)
QT Modbus RTU调试助手(包含算法实现CRC MODBUS16校验)
438 0
|
7月前
|
算法
异或算法
异或算法
|
7月前
|
存储 算法 安全
C# | 上位机开发新手指南(五)校验算法——CRC
当我们在进行数据传输时,可能会因为信道噪声、干扰等因素导致数据出现错误,从而影响传输的可靠性和准确性。此时,我们需要一种方法来检测数据是否出现错误,并尽可能快速地发现和纠正错误。CRC(Cyclic Redundancy Check)校验算法就是一种常用的数据校验方法,它通过对数据进行处理生成校验码,从而实现对数据的完整性和准确性进行验证。 使用CRC校验的意义在于能够提高数据传输的可靠性,降低数据传输错误率,确保数据的完整性和准确性。在各个领域中,如通信、网络、存储等,CRC校验都得到了广泛的应用。
339 0
C# | 上位机开发新手指南(五)校验算法——CRC
|
7月前
|
算法 C#
C# | 上位机开发新手指南(四)校验算法
校验算法是一种用于验证数据传输过程中是否出现错误或丢失的算法。 在数据传输过程中,由于噪声、干扰、传输错误等因素的影响,会导致数据传输过程中出现错误或丢失。 为了保证数据传输的准确性,需要在数据传输过程中添加校验码。发送端通过计算数据的校验码并将其附加到数据中一起发送出去,接收端再次计算校验码并将其与接收到的校验码进行比较,如果两者相同,则说明数据传输过程中没有出现错误或丢失。
270 0
C# | 上位机开发新手指南(四)校验算法
|
7月前
|
算法 前端开发
前端算法-二进制求和
前端算法-二进制求和
|
算法 测试技术 C#
C++字典树算法:找出强数对的最大异或值 II
C++字典树算法:找出强数对的最大异或值 II
|
1天前
|
机器学习/深度学习 算法
基于改进遗传优化的BP神经网络金融序列预测算法matlab仿真
本项目基于改进遗传优化的BP神经网络进行金融序列预测,使用MATLAB2022A实现。通过对比BP神经网络、遗传优化BP神经网络及改进遗传优化BP神经网络,展示了三者的误差和预测曲线差异。核心程序结合遗传算法(GA)与BP神经网络,利用GA优化BP网络的初始权重和阈值,提高预测精度。GA通过选择、交叉、变异操作迭代优化,防止局部收敛,增强模型对金融市场复杂性和不确定性的适应能力。
102 80
|
20天前
|
算法
基于WOA算法的SVDD参数寻优matlab仿真
该程序利用鲸鱼优化算法(WOA)对支持向量数据描述(SVDD)模型的参数进行优化,以提高数据分类的准确性。通过MATLAB2022A实现,展示了不同信噪比(SNR)下模型的分类误差。WOA通过模拟鲸鱼捕食行为,动态调整SVDD参数,如惩罚因子C和核函数参数γ,以寻找最优参数组合,增强模型的鲁棒性和泛化能力。
|
26天前
|
机器学习/深度学习 算法 Serverless
基于WOA-SVM的乳腺癌数据分类识别算法matlab仿真,对比BP神经网络和SVM
本项目利用鲸鱼优化算法(WOA)优化支持向量机(SVM)参数,针对乳腺癌早期诊断问题,通过MATLAB 2022a实现。核心代码包括参数初始化、目标函数计算、位置更新等步骤,并附有详细中文注释及操作视频。实验结果显示,WOA-SVM在提高分类精度和泛化能力方面表现出色,为乳腺癌的早期诊断提供了有效的技术支持。
|
6天前
|
供应链 算法 调度
排队算法的matlab仿真,带GUI界面
该程序使用MATLAB 2022A版本实现排队算法的仿真,并带有GUI界面。程序支持单队列单服务台、单队列多服务台和多队列多服务台三种排队方式。核心函数`func_mms2`通过模拟到达时间和服务时间,计算阻塞率和利用率。排队论研究系统中顾客和服务台的交互行为,广泛应用于通信网络、生产调度和服务行业等领域,旨在优化系统性能,减少等待时间,提高资源利用率。