STM32浮点型变量数值大小边界判断有误的问题的原因及解决方案

1. 问题描述

  在使用STM32G431RBT6芯片的开发板的时候,要实现如下图所示的一个按键控制一个浮点型变量的累加与到达边界值清零的功能。
在这里插入图片描述
只关于这一部分功能的代码段如下

float x = 0;				// 浮点型变量初始化
/* 中间的其它代码与该问题无关,这里省略,只保留功能相关代码 */
if(ucKey_Down == 1)			// 按下B1
{
	if(x < 3.3)
	{
		x += 0.3;
	}
	else if(x >= 3.3)
	{
		x = 0;
	}
}

但是当使用LCD将该值输出时,发现了奇怪的一幕,变量x竟然增加到了3.6后才清零。
在这里插入图片描述

2. 发现原因

  使用了调试功能后,发现了原因。
在这里插入图片描述
原来当LCD显示x值为3.3的时候,x实际值是3.29999971,对于程序中的判断而言,仍比3.3小,所以下一次按下按键,仍然会使该变量加0.3,才有了显示3.6的结果。
  至于为什么会出现这样的情况,个人认为是由于浮点型变量与其他变量一样,都是按照二进制存储的,所以事实上在存储变量时,整数部分的数值存储是可以实现十进制与二进制的完全无误差转化的,但是小数部分的存储数值的最小精度的单位并不是按照十进制的10的负几次方,而是二进制存储的精度,也就是最小计数单位2的负几次方,所以计数单位无法完全按照十进制的小数点的精度。对于每次递增的数值0.3不能完全表示成2的负幂指数之和的形式,所以在0.3这个立即数在存储时本身就带有误差。当然,如果在浮点型变量x的初始化时,初始化给x的值的小数部分不能表示成2的负整数幂次之和的形式,那么x的初始化的值同样会在小数的最后几位出现误差,例如

float x = 2.4;

感兴趣的可以尝试一下。
  虽然在正常计算和显示数值时可以通过四舍五入直接忽略这一小点误差,但是当做边界判断时,这点误差将可能对程序起到决定性作用。

3. 检验猜测

  考虑浮点型变量的小数部分的存储数值为2的负整数幂指数为计算精度的,那么对于小数部分可以表示为若干个2的负幂指数之和的形式的数值,应该就可以实现完全无误差转化了。那么修改上述递增数值重新测试,修改的该部分代码改为

float x = 0;				// 浮点型变量初始化
/* 中间的其它代码与该问题无关,这里省略,只保留功能相关代码 */
if(ucKey_Down == 1)			// 按下B1
{
	if(x < 3.375)
	{
		x += 0.375;
	}
	else if(x >= 3.375)
	{
		x = 0;
	}
}

0.375 = 2 − 1 + 2 − 2 0.375=2^{-1}+2^{-2} 0.375=21+22。调试代码,当x加到最大值时得到结果x=3.375,且没有误差。
在这里插入图片描述
因而可以验证前面原因的猜测是正确的。

4.解决方法

  为了避免因为存储误差带来的赋值细微误差造成的边界判断出错的问题,可以考虑在边界判断时进行宽松处理,如当判断条件中是小于号“<”接边界值时,即if(x<bound),对则对边界值在功能误差容许范围内进行细微减小处理,如将前面的判断3.3为x的上界的代码改写为

float x = 0;				// 浮点型变量初始化
/* 中间的其它代码与该问题无关,这里省略,只保留功能相关代码 */
if(ucKey_Down == 1)			// 按下B1
{
	if(x < 3.29)
	{
		x += 0.3;
	}
	else if(x >= 3.29)
	{
		x = 0;
	}
}

就可以实现在x理论值为3.3时,再次按下按键B1,x将回到0,实现了符合要求的循环递增。类似地,如果判断的条件是大于边界值,那么就作增大判断边界值的宽松处理,如

float x = 3.0;				// 浮点型变量初始化
/* 中间的其它代码与该问题无关,这里省略,只保留功能相关代码 */
if(ucKey_Down == 1)			// 按下B1
{
	if(x >= 0.01)
	{
		x -= 0.3;
	}
	else if(x < 0.01)
	{
		x = 3.3;
	}
}

就可以实现每次按下B1按键x递减0.3,直到减到理论值0时,x变为3.3,实现循环递减。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv8蒸馏 | 知识蒸馏 | 利用模型蒸馏改进YOLOv8进行无损涨点 | MimicLoss(在线蒸馏 + 离线蒸馏)

一、本文介绍 这篇文章给大家带来的是模型的蒸馏&#xff0c;利用教师模型指导学生模型从而进行模型的涨点&#xff0c;本文的内容不仅可以用于论文中&#xff0c;在目前的绝大多数的工作中模型蒸馏是一项非常重要的技术&#xff0c;所以大家可以仔细学习一下本文的内容&#…

redis 未授权访问漏洞详解

1、漏洞原理&#xff1a; 1、redis 绑定在6379端口&#xff0c;且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略&#xff0c;直接暴露在公网。 2、没有设置密码认证&#xff08;默认密码为空&#xff09;&#xff0c;可以免密码远程登录redis服务。 2、漏洞…

项目大集成

一 keeplived 高可用 192.168.11.11nginx keeplived192.168.11.12nginx keeplived 两台均编译安装服务器 1 主服务器修改文件&#xff1a; 2 备服务器修改文本 scp keepalived.conf 192.168.11.12:/etc/keepalived/ 3 给主服务器添加虚拟ip ifconfig ens33:0 192.168…

DHCP服务器配置故障转移后显示红色箭头、与伙伴服务器失去联系的解决方案

一、遇到的故障现象&#xff1a; &#xff08;主DHCP服务器与备用DHCP服务器连通性正常&#xff0c;在故障转移选项卡上却显示与伙伴失去联系、伙伴关闭&#xff0c;且ipv4协议旁边显示一个红色的小箭头&#xff09;&#xff0c;正常情况下是绿色 &#xff08;一&#xff09;…

Unity场景光照数据Light data asset

首先描述一下遇到的问题&#xff0c;游戏运行过程中切换场景之后发现模型接收的光照不对。 Unity编辑模式下正常显示&#xff1a; 运行模式下从其他场景切入之后显示异常&#xff1a; 排查了灯光参数和环境光以及着色器都没发现异常。 根据ChatGPT的回答&#xff0c;问题可能…

viewerjs在vue中实现点击图片预览、切换、缩放、拖拽、旋转等功能

1、下载依赖&#xff1a; npm i viewerjs 2、定义html结构 <template> <div><ul class"artBody"><li><img src"picture-1.jpg" alt"Picture 1"></li><li><img src"picture-2.jpg" alt&…

编写一款2D CAD/CAM软件(十六)交互绘制图形

绘制步骤 以交互绘制圆形为例&#xff1a; 点击鼠标左键&#xff0c;确定圆心位置&#xff1b;抬起鼠标&#xff0c;移动鼠标&#xff0c;半径随鼠标位置变化&#xff1b;点击左键确定半径&#xff0c;完成圆的绘制。 绘制结果 Code /// j-operator-create-circle.h#pragma…

node.js-包

包的概念 包&#xff1a;将模块&#xff0c;代码&#xff0c;其他资料聚合成的一个文件夹 包分类&#xff1a; 1.项目包&#xff1a;主要用于编写项目和业务逻辑的文件夹 2.软件包&#xff1a;封装工具和方法供开发者使用&#xff08;一般使用npm管理&#xff09; 1&#…

Topaz Photo AI 3.0.0 (macOS Universal) - AI 图片修复工具

Topaz Photo AI 3.0.0 (macOS Universal) - AI 图片修复工具 Maximize Image Quality with AI 请访问原文链接&#xff1a;Topaz Photo AI 3.0.0 (macOS Universal) - AI 图片修复工具&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sy…

Sound Siphon for Mac:音频处理与录制工具

Sound Siphon for Mac是一款专为Mac用户设计的音频处理与录制工具&#xff0c;以其出色的性能、丰富的功能和简便的操作而备受赞誉。 Sound Siphon for Mac v3.6.8激活版下载 该软件支持多种音频格式&#xff0c;包括MP3、WAV、AAC、FLAC等&#xff0c;用户可以轻松导入各种音频…

Acer宏碁掠夺者战斧300笔记本电脑PH315-52工厂模式原装Win10系统安装包 恢复出厂开箱状态 带恢复重置

宏碁掠夺者PH315-52原厂Windows10工厂包镜像下载&#xff0c;预装oem系统 链接&#xff1a;https://pan.baidu.com/s/1grmJzz6nW1GOaImY_ymXGw?pwdi286 提取码&#xff1a;i286 原厂W10系统自带所有驱动、PredatorSense风扇键盘控制中心、Office办公软件、出厂主题壁纸、系统…

为何3D动画工作室偏爱使用在线渲染农场?

随着市场需求的不断增长和生产挑战的加剧&#xff0c;3D动画工作室面临着前所未有的压力。为了有效应对这些挑战&#xff0c;众多工作室选择了使用网络渲染农场。这种选择使他们能够借助网络渲染农场的强大渲染能力和高度灵活的资源配置&#xff0c;以此优化他们的工作流程&…

excel文件可以直接转换成图片格式吗?excel文件怎样才能快速转换成图片?excel文件快速转换成图片的方法

一&#xff0c;excel文件转图片的必要性 1&#xff0c;excel文件转图片可以提高信息传播的便捷性。在日常工作中&#xff0c;我们可能需要将表格数据分享给同事或客户&#xff0c;但由于Excel文件的复杂性&#xff0c;对方可能需要安装相应的软件才能查看。而如果将Excel文件转…

去雾笔记-Pixel Shuffle,逆Pixel Shuffle,棋盘效应,转置卷积

文章目录 1.Pixel Shuffle2.Inverse Pixel Shuffle3.棋盘效应4.转置卷积5.宽激活块6.PSPNet7.反射填充层&#xff08;Reflective Padding Layer&#xff09;8.tanh层 1.Pixel Shuffle Pixel Shuffle是一种用于图像超分辨率的技术&#xff0c;它通过重新排列图像的像素来增加图…

vue3组件封装系列-表单请求

我们在开发一些后台管理系统时&#xff0c;总是会写很多的列表查询页面&#xff0c;如果不封装组件&#xff0c;就会无限的复制粘贴&#xff0c;而且页面很冗余&#xff0c;正常情况下&#xff0c;我们都是要把组件进行二次封装&#xff0c;来达到我们想要效果。这里我分享一下…

centos执行mpd遇到bash:mpd:command not found错误

错误原因 我用的版本是centos7及mpich-3.2。在搭建mpi并行计算时&#xff0c;按照很多教程说的使用mpd&#xff0c;但是遇到了bash&#xff1a;mpd&#xff1a;command not found错误&#xff08;见下图&#xff09;&#xff0c;我尝试着去装mpd&#xff0c;未果&#xff1b;也…

深度学习500问——Chapter08:目标检测(3)

文章目录 8.2.7 DetNet 8.2.8 CBNet 8.2.7 DetNet DetNet是发表在ECCV2018的论文&#xff0c;出发点是现有的检测任务backbone都是从分类任务衍生而来的&#xff0c;因此作者想针对检测专用的backbone做一些讨论和研究而设计了DetNet&#xff0c;思路比较新奇。 1. Introduct…

Linux查看僵尸进程

1、查看系统是否有僵尸进程 使用Top命令查找&#xff0c;当zombie前的数量不为0时&#xff0c;即系统内存在相应数量的僵尸进程。 2、定位僵尸进程 使用命令ps -A -ostat,ppid,pid,cmd |grep -e ‘^[Zz]’定位僵尸进程以及该僵尸进程的父进程。 3、杀死僵尸进程 使用Kill -…

【NLP练习】使用Word2Vec实现文本分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、数据预处理 1. 任务说明 本次加入Word2Vec使用PyTorch实现中文文本分类&#xff0c;Word2Vec则是其中的一种词嵌入方法&#xff0c;是一种用于生成词向量…

【多态】底层原理

博主首页&#xff1a; 有趣的中国人 专栏首页&#xff1a; C进阶 本篇文章主要讲解 多态底层原理 的相关内容 1. 多态原理 1.1 虚函数表 先看一下这段代码&#xff0c;计算一下sizeof(Base)是多少&#xff1a; class Base { public:virtual void Func1(){cout << &quo…