【C语言】通用统计数据结构及其更新函数(最值、变化量、总和、平均数、方差等)
【C语言】通用统计数据结构及其更新函数(最值、变化量、总和、平均数、方差等)
更新以gitee为准:
gitee
文章目录
- 通用统计数据结构
- 更新函数
- 附录:压缩字符串、大小端格式转换
- 压缩字符串
- 浮点数
- 压缩Packed-ASCII字符串
- 大小端转换
- 什么是大端和小端
- 数据传输中的大小端
- 总结
- 大小端转换函数
通用统计数据结构
为了综合常见的统计数据计算 但又不导入math库、开平方根等耗时算法,可以按如下定义结构:
#define FMIN(a,b) ((a) < (b) ? (a) : (b))
#define FMAX(a,b) ((a) > (b) ? (a) : (b))typedef struct
{float sum;int num;float min;float max;float avg;float delta;float m2; // 二阶中心矩float population_var; // 总体方差float sample_var; // 样本方差
} StatResultType;
如果需要计算标准差,则通过方差求平方根来求解
大小比较通过宏来实现
更新函数
满足该更新函数的内容如下:
void UpdateStatResult(StatResultType* res, float new_val)
{if(res->num++ == 0){res->min = res->max = new_val;res->sum = new_val;res->avg = new_val;res->delta = 0;res->m2 = 0;res->sample_var = 0; // 初始化为0res->population_var = 0;return;}// 极值比较res->min = FMIN(res->min, new_val);res->max = FMAX(res->max, new_val);// 增量更新(Welford算法)const float delta = new_val - res->avg;res->sum += new_val;const float new_avg = res->avg + delta / res->num;const float delta2 = new_val - new_avg;res->m2 += delta * delta2;res->avg = new_avg;// 计算衍生统计量res->delta = res->max - res->min;const uint32_t n = res->num;if(n > 1){res->population_var = res->m2 / n;res->sample_var = res->m2 / (n - 1);}else{res->population_var = res->sample_var = 0;}
}
附录:压缩字符串、大小端格式转换
压缩字符串
首先HART数据格式如下:


重点就是浮点数和字符串类型
Latin-1就不说了 基本用不到
浮点数
浮点数里面 如 0x40 80 00 00表示4.0f
在HART协议里面 浮点数是按大端格式发送的 就是高位先发送 低位后发送
发送出来的数组为:40,80,00,00
但在C语言对浮点数的存储中 是按小端格式来存储的 也就是40在高位 00在低位
浮点数:4.0f
地址0x1000对应00
地址0x1001对应00
地址0x1002对应80
地址0x1003对应40
若直接使用memcpy函数 则需要进行大小端转换 否则会存储为:
地址0x1000对应40
地址0x1001对应80
地址0x1002对应00
地址0x1003对应00
大小端转换:
void swap32(void * p)
{uint32_t *ptr=p;uint32_t x = *ptr;x = (x << 16) | (x >> 16);x = ((x & 0x00FF00FF) << 8) | ((x >> 8) & 0x00FF00FF);*ptr=x;
}
压缩Packed-ASCII字符串
本质上是将原本的ASCII的最高2位去掉 然后拼接起来 比如空格(0x20)
四个空格拼接后就成了
1000 0010 0000 1000 0010 0000
十六进制:82 08 20
对了一下表 0x20之前的识别不了
也就是只能识别0x20-0x5F的ASCII表

压缩/解压函数后面再写:
//传入的字符串和数字必须提前声明 且字符串大小至少为str_len 数组大小至少为str_len%4*3 str_len必须为4的倍数
uint8_t Trans_ASCII_to_Pack(uint8_t * str,uint8_t * buf,const uint8_t str_len)
{if(str_len%4){return 0;}uint8_t i=0;memset(buf,0,str_len/4*3); for(i=0;i<str_len;i++){if(str[i]==0x00){str[i]=0x20;}}for(i=0;i<str_len/4;i++){buf[3*i]=(str[4*i]<<2)|((str[4*i+1]>>4)&0x03);buf[3*i+1]=(str[4*i+1]<<4)|((str[4*i+2]>>2)&0x0F);buf[3*i+2]=(str[4*i+2]<<6)|(str[4*i+3]&0x3F);}return 1;
}//传入的字符串和数字必须提前声明 且字符串大小至少为str_len 数组大小至少为str_len%4*3 str_len必须为4的倍数
uint8_t Trans_Pack_to_ASCII(uint8_t * str,uint8_t * buf,const uint8_t str_len)
{if(str_len%4){return 0;}uint8_t i=0;memset(str,0,str_len);for(i=0;i<str_len/4;i++){str[4*i]=(buf[3*i]>>2)&0x3F;str[4*i+1]=((buf[3*i]<<4)&0x30)|(buf[3*i+1]>>4);str[4*i+2]=((buf[3*i+1]<<2)&0x3C)|(buf[3*i+2]>>6);str[4*i+3]=buf[3*i+2]&0x3F;}return 1;
}
大小端转换
在串口等数据解析中 难免遇到大小端格式问题
什么是大端和小端
所谓的大端模式,就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
所谓的小端模式,就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
简单来说:大端——高尾端,小端——低尾端
举个例子,比如数字 0x12 34 56 78在内存中的表示形式为:
1)大端模式:
低地址 -----------------> 高地址
0x12 | 0x34 | 0x56 | 0x78
2)小端模式:
低地址 ------------------> 高地址
0x78 | 0x56 | 0x34 | 0x12
可见,大端模式和字符串的存储模式类似。
数据传输中的大小端
比如地址位、起止位一般都是大端格式
如:
起始位:0x520A
则发送的buf应为{0x52,0x0A}
而数据位一般是小端格式(单字节无大小端之分)
如:
一个16位的数据发送出来为{0x52,0x0A}
则对应的uint16_t类型数为: 0x0A52
而对于浮点数4.0f 转为32位应是:
40 80 00 00
以大端存储来说 发送出来的buf就是依次发送 40 80 00 00
以小端存储来说 则发送 00 00 80 40
由于memcpy等函数 是按字节地址进行复制 其复制的格式为小端格式 所以当数据为小端存储时 不用进行大小端转换
如:
uint32_t dat=0;
uint8_t buf[]={0x00,0x00,0x80,0x40};memcpy(&dat,buf,4);float f=0.0f;f=*((float*)&dat); //地址强转printf("%f",f);
或更优解:
uint8_t buf[]={0x00,0x00,0x80,0x40}; float f=0.0f;memcpy(&f,buf,4);
而对于大端存储的数据(如HART协议数据 全为大端格式) 其复制的格式仍然为小端格式 所以当数据为小端存储时 要进行大小端转换
如:
uint32_t dat=0;
uint8_t buf[]={0x40,0x80,0x00,0x00};memcpy(&dat,buf,4);float f=0.0f;swap32(&dat); //大小端转换f=*((float*)&dat); //地址强转printf("%f",f);
或:
uint8_t buf[]={0x40,0x80,0x00,0x00};memcpy(&dat,buf,4);float f=0.0f;swap32(&f); //大小端转换printf("%f",f);
或更优解:
uint32_t dat=0;
uint8_t buf[]={0x40,0x80,0x00,0x00};float f=0.0f;dat=(buf[0]<<24)|(buf[0]<<16)|(buf[0]<<8)|(buf[0]<<0)f=*((float*)&dat);
总结
固 若数据为小端格式 则可以直接用memcpy函数进行转换 否则通过移位的方式再进行地址强转
对于多位数据 比如同时传两个浮点数 则可以定义结构体之后进行memcpy复制(数据为小端格式)
对于小端数据 直接用memcpy写入即可 若是浮点数 也不用再进行强转
对于大端数据 如果不嫌麻烦 或想使代码更加简洁(但执行效率会降低) 也可以先用memcpy写入结构体之后再调用大小端转换函数 但这里需要注意的是 结构体必须全为无符号整型 浮点型只能在大小端转换写入之后再次强转 若结构体内采用浮点型 则需要强转两次
所以对于大端数据 推荐通过移位的方式来进行赋值 然后再进行个别数的强转 再往通用结构体进行写入
多个不同变量大小的结构体 要主要字节对齐的问题
可以用#pragma pack(1) 使其对齐为1
但会影响效率
大小端转换函数
直接通过对地址的操作来实现 传入的变量为32位的变量
中间变量ptr是传入变量的地址
void swap16(void * p)
{uint16_t *ptr=p;uint16_t x = *ptr;x = (x << 8) | (x >> 8);*ptr=x;
}void swap32(void * p)
{uint32_t *ptr=p;uint32_t x = *ptr;x = (x << 16) | (x >> 16);x = ((x & 0x00FF00FF) << 8) | ((x >> 8) & 0x00FF00FF);*ptr=x;
}void swap64(void * p)
{uint64_t *ptr=p;uint64_t x = *ptr;x = (x << 32) | (x >> 32);x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x >> 16) & 0x0000FFFF0000FFFF);x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x >> 8) & 0x00FF00FF00FF00FF);*ptr=x;
}
相关文章:
【C语言】通用统计数据结构及其更新函数(最值、变化量、总和、平均数、方差等)
【C语言】通用统计数据结构及其更新函数(最值、变化量、总和、平均数、方差等) 更新以gitee为准: gitee 文章目录 通用统计数据结构更新函数附录:压缩字符串、大小端格式转换压缩字符串浮点数压缩Packed-ASCII字符串 大小端转换什…...
Spring AI(10)——STUDIO传输的MCP服务端
Spring AI MCP(模型上下文协议)服务器Starters提供了在 Spring Boot 应用程序中设置 MCP 服务器的自动配置。它支持将 MCP 服务器功能与 Spring Boot 的自动配置系统无缝集成。 本文主要演示支持STDIO传输的MCP服务器 仅支持STDIO传输的MCP服务器 导入j…...
Sklearn 机器学习 缺失值处理 填充数据列的缺失值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 💡使用 Scikit-learn 处理数据缺失值的完整指南 在机器学习项目中,数据缺失是不可避…...
猜字符位置游戏-position gasses
import java.util.*;public class Main {/*字符猜位置游戏;每次提交只能被告知答对几个位置;根据提示答对的位置数推测出每个字符对应的正确位置;*/public static void main(String[] args) {char startChar A;int gameLength 8;List<String> ballList new ArrayList&…...
宝塔安装配置FRP
FRP(Fast Reverse Proxy)作为一款高性能的反向代理应用,能够帮助我们轻松实现内网穿透,将内网服务暴露到公网,满足远程访问、开发调试等多种需求。宝塔面板以其简洁易用的界面和强大的功能,成为众多站长和开…...
元器件基础学习笔记——结型场效应晶体管 (JFET)
场效应晶体管(Field Effect Transistor,FET)简称场效应管,是一种三端子半导体器件,它根据施加到其其中一个端子的电场来控制电流的流动。与双极结型晶体管 (BJT) 不同,场效应晶体管 …...
tableau 实战工作场景常用函数与LOD表达式的应用详解
这是tableau实战工作场景图表制作第七期--常用函数与LOD表达式的应用 数据资源已经与这篇博客捆绑,有需要者可以下载通过网盘分享的文件:3.2-8月成交数据.xlsx等3个文件 链接: https://pan.baidu.com/s/17WtUoZTqzoNo5kTFjua4hw?pwd0623 提取码: 06…...
智能终端与边缘计算按章复习
第1章:智能终端与边缘计算概述 简述计算机网络和Web技术发展过程中,信息和运算从用户本地向Web服务器迁移的趋势,并解释这一过程如何逐步形成了如今的云计算形态。 随着计算机网络和Web技术的不断发展,信息和运算的重心发生了显著…...
C#面试问题61-80
66. What is reflection? 反射是一种机制,它使我们能够编写可以检查应用程序中所 用类型的代码。例如,调用名称与给定字符串相等的方法,或者列出属于给定 对象的所有字段及其值。 在 Convert 方法中,我们根本不知道处理的是什么…...
分布式Session处理的五大主流方案解析
在分布式环境下,Session 处理的核心挑战是确保用户请求在不同服务器间流转时能保持会话状态一致。以下是主流解决方案及优缺点分析: 🔐 一、集中存储方案(主流推荐) Redis/Memcached 存储 原理:将 Session…...
C++ 中的 const 知识点详解,c++和c语言区别
目录 一。C 中的 const 知识点详解1. 基本用法1.1) 定义常量1.2) 指针与 const 2. 函数中的 const2.1)const 参数2.2)const 成员函数 3. 类中的 const3.1)const 成员变量3.2)const 对象 4. const 返回值5. …...
《PyTorch:开启深度学习新世界的魔法之门》
一、遇见 PyTorch:深度学习框架新星登场 在当今的技术领域中,深度学习已然成为推动人工智能发展的核心动力,而深度学习框架则是这场技术革命中的关键工具。在众多深度学习框架里,PyTorch 以其独特的魅力和强大的功能,迅速崛起并占据了重要的地位,吸引着无数开发者和研究者…...
分布式光纤传感(DAS)技术应用解析:从原理到落地场景
近年来,分布式光纤传感(Distributed Acoustic Sensing,DAS)技术正悄然改变着众多传统行业的感知方式。它将普通的通信光缆转化为一个长距离、连续分布的“听觉传感器”,对振动、声音等信号实现高精度、高灵敏度的监测。…...
Spring事务回滚在系统中的应用
以文章发布为例,介绍Spring事务回滚在系统中的应用 事务回滚的核心概念 事务回滚是数据库管理系统中的关键机制,它确保数据库操作要么全部成功,要么全部失败。在Spring框架中,我们可以通过Transactional注解轻松实现事务管理。 …...
.Net Framework 4/C# 属性和方法
一、属性的概述 属性是对实体特征的抽象,用于提供对类或对象的访问,C# 中的属性具有访问器,这些访问器指定在它们的值被读取或写入时需要执行的语句,因此属性提供了一种机制,用于把读取和写入对象的某些特征与一些操作…...
ASP.NET Core使用Quartz部署到IIS资源自动被回收解决方案
iis自动回收的原因 回收机制默认配置,间隔时间是1740分钟,意思是:默认情况下每1740分钟(29小时)回收一次,定期检查应用程序池中的工作进程,并终止那些已经存在很长时间或已经使用了太多资源的工作进程 进程模型默认配…...
Fullstack 面试复习笔记:Spring / Spring Boot / Spring Data / Security 整理
Fullstack 面试复习笔记:Spring / Spring Boot / Spring Data / Security 整理 之前的笔记: Fullstack 面试复习笔记:操作系统 / 网络 / HTTP / 设计模式梳理Fullstack 面试复习笔记:Java 基础语法 / 核心特性体系化总结Fullsta…...
调用.net DLL让CANoe自动识别串口号
1.前言 CANoe9.0用CAPL控制数控电源_canoe读取程控电源电流值-CSDN博客 之前做CAPL通过串口控制数控电源,存在一个缺点:更换电脑需要改串口号 CSDN上有类似的博客,不过要收费,本文根据VID和PID来自动获取串口号,代码…...
第5章:Cypher查询语言进阶
在掌握了Cypher的基础知识后,本章将深入探讨更高级的查询技术。这些进阶技能将帮助您构建更复杂、更高效的查询,解决实际业务中的复杂问题,并充分发挥Neo4j的图数据处理能力。 5.1 复杂查询构建 随着业务需求的复杂性增加,查询也…...
【Python进阶】元类编程
目录 🌟 前言🏗️ 技术背景与价值🩹 当前技术痛点🛠️ 解决方案概述👥 目标读者说明 🧠 一、技术原理剖析📊 核心概念图解💡 核心作用讲解🔧 关键技术模块说明⚖️ 技术选…...
算法(蓝桥杯学习C/C++版)
up: 溶金落梧桐 溶金落梧桐的个人空间-溶金落梧桐个人主页-哔哩哔哩视频 蓝桥杯三十天冲刺系列 BV18eQkY3EtP 网站: OI Wiki OI Wiki - OI Wiki 注意 比赛时,devc勾选c11(必看) 必须勾选c11一共有两个方法,任用…...
Docker镜像无法拉取问题解决办法
最近再学习RabbitMQ,需要从Docker镜像中拉取rabbitMQ,但是下拉失败 总的来说就是无法和docker镜像远程仓库建立连接 我又去尝试ping docker.io发现根本没有反应,还是无法连接找了许多办法还是没有办法解决,最后才发现是镜像问题&a…...
ZephyrOS 嵌入式开发Black Pill V1.2之Debug调试器
版本和环境信息如下: PC平台: Windows 11 专业版 Zephyr开发环境:v4.1.0 Windows 下搭建 Zephyr 开发环境 WeAct BlackPill V1.2开发板: WeAct STM32F411CEU6 BlackPill 核心板 Debug调试器: ST-LINK V2: ST-LINK V2 S…...
# 主流大语言模型安全性测试(二):英文越狱提示词下的表现与分析
主流大语言模型安全性测试(二):英文越狱提示词下的表现与分析 在上一篇文章中,我们对多个主流大语言模型(LLM)进行了中文诱导性提示词的越狱测试,评估其是否能够在面对非法、有害或危险内容请求…...
SAP 在 AI 与数据统一平台上的战略转向
在 2025 年 SAP Sapphire 大会上,SAP 展示了其最新的产品战略和技术整合方向,与以往不同的是,今年的讨论更加务实、聚焦客户实际需求。SAP 强调,ERP 的转型不再是“一刀切”或破坏性的,而是可以根据客户现状࿰…...
服务器磁盘空间被Docker容器日志占满处理方法
事发场景: 原本正常的服务停止运行了,查看时MQTT服务链接失败,查看对应的容器服务发现是EMQX镜像停止运行了,重启也是也报错无法正常运行,报错如下图: 报错日志中连续出现两个"no space left on devi…...
c++学习-this指针
1.基本概念 非静态成员函数都会默认传递this指针(静态成员函数属于类本身,不属于某个实例对象),方便访问对象对类成员变量和 成员函数。 2.基本使用 编译器实际处理类成员函数,this是第一个隐藏的参数,类…...
交易所系统攻坚:高并发撮合引擎与合规化金融架构设计
交易所系统攻坚:高并发撮合引擎与合规化金融架构设计 ——2025年数字资产交易平台的性能与合规双轮驱动 一、高并发撮合引擎:从微秒级延迟到百万TPS 核心架构设计 订单簿优化:数据结构创新:基于红黑树与链表混合存储,…...
OpenCV计算机视觉实战(10)——形态学操作详解
OpenCV计算机视觉实战(10)——形态学操作详解 0. 前言1. 腐蚀与膨胀1.1 为什么要做腐蚀与膨胀1.2 OpenCV 实现 2. 开运算与闭运算2.1 开运算与闭运算原理2.2 OpenCV 实现 3. 形态学梯度与骨架提取3.1 形态学梯度3.2 骨架提取 小结系列链接 0. 前言 形态…...
libiec61850 mms协议异步模式
之前项目中使用到libiec61850库,都是服务端开发。这次新的需求要接收服务端的遥测数据,这就涉及到客户端开发了。 客户端开发没搞过啊,挑战不少,但是人不就是通过战胜困难才成长的嘛。通过查看libiec61850的客户端API发现…...
