阐述 C 语言中的浮点数精度问题?

C语言

🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!
📙C 语言百万年薪修炼课程 【https://dwz.mosong.cc/cyyjc】通俗易懂,深入浅出,匠心打磨,死磕细节,6年迭代,看过的人都说好。

分割线

文章目录

  • C 语言中的浮点数精度问题
  • 一、浮点数的表示
  • 二、精度的限制
    • 1. 舍入误差
    • 2. 有效数字
  • 三、精度问题的影响
    • 1. 数值比较
    • 2. 算术运算
    • 3. 累计误差
  • 四、解决方案
    • 1. 使用更高精度的类型
    • 2. 避免直接比较浮点数是否相等
    • 3. 尽量减少浮点数的运算次数
    • 4. 注意数值范围
  • 五、示例分析
    • 示例 1:浮点数比较错误
    • 示例 2:累加误差
    • 示例 3:正确的浮点数比较
  • 六、总结

分割线


C 语言中的浮点数精度问题

在 C 语言中,浮点数(float 和 double 类型)的精度是一个重要且容易引起困惑的概念。理解浮点数的精度问题对于编写正确和可靠的程序至关重要。

一、浮点数的表示

浮点数在计算机中的存储方式遵循 IEEE 754 标准。在这个标准中,浮点数被分为三个部分:符号位、指数位和尾数位。

以单精度浮点数(float 类型,通常占用 4 个字节,32 位)为例:

  • 符号位:1 位,用于表示数的正负。
  • 指数位:8 位,用于表示指数的值。
  • 尾数位:23 位,用于表示小数部分。

双精度浮点数(double 类型,通常占用 8 个字节,64 位)具有更高的精度:

  • 符号位:1 位。
  • 指数位:11 位。
  • 尾数位:52 位。

二、精度的限制

由于浮点数的存储方式和有限的位数,它们存在精度上的限制。

1. 舍入误差

在将一个十进制的小数转换为二进制表示并存储为浮点数时,可能会发生舍入。例如,将 0.1 转换为二进制时,会得到一个无限循环的二进制小数,在存储时必须进行截断或舍入,从而导致精度损失。

float num1 = 0.1f;
printf("0.1f = %f\n", num1); 

在上述示例中,输出的结果可能不是精确的 0.1。

2. 有效数字

float 类型通常能保证 6 - 7 位有效数字的精度,而 double 类型能保证 15 - 16 位有效数字的精度。

float num2 = 3.1415926f;
double num3 = 3.1415926;
printf("float: 3.1415926f = %f\n", num2);
printf("double: 3.1415926 = %lf\n", num3);

可以看到,使用 float 存储时,后面的数字可能不准确。

三、精度问题的影响

1. 数值比较

由于精度问题,直接对浮点数进行相等性比较可能会产生错误的结果。

float a = 0.1f;
float b = 0.1f;
if (a == b) {printf("Equal\n");
} else {printf("Not Equal\n");
}

在某些情况下,尽管直观上认为 a 和 b 应该相等,但由于精度误差,可能会得出“Not Equal”的结果。

正确的比较方式是考虑一个误差范围:

#define EPSILON 0.00001if (fabs(a - b) < EPSILON) {printf("Equal within tolerance\n");
} else {printf("Not Equal\n");
}

2. 算术运算

在进行浮点数的算术运算时,也可能出现精度问题。

float num4 = 1000000.0f;
float num5 = 0.00001f;
float result = num4 + num5;
printf("Result: %f\n", result);

可能会发现结果并不完全符合预期,因为在加法运算中出现了精度损失。

3. 累计误差

当对浮点数进行多次运算和累加时,精度误差可能会累积,导致结果的偏差越来越大。

float sum = 0.0f;
for (int i = 0; i < 1000000; i++) {sum += 0.00001f;
}
printf("Sum: %f\n", sum);

最终的 sum 值可能与预期的 100 相差较大。

四、解决方案

1. 使用更高精度的类型

如果对精度要求较高,可以使用 double 类型代替 float 类型。但需要注意的是,double 类型也不是无限精度的。

2. 避免直接比较浮点数是否相等

如前文所述,使用误差范围进行比较。

3. 尽量减少浮点数的运算次数

特别是在涉及多次累加或复杂运算时,可以考虑优化算法或采用其他数据类型(如整数)进行中间计算。

4. 注意数值范围

确保所操作的浮点数在其可表示的数值范围内,避免出现上溢或下溢的情况。

五、示例分析

示例 1:浮点数比较错误

#include <stdio.h>int main() {float x = 0.1f;float y = 0.100000001490116119384765625f;if (x == y) {printf("Equal\n");} else {printf("Not Equal\n");}return 0;
}

在这个示例中,直观上认为 0.1 和 0.100000001490116119384765625 很接近,应该被认为相等,但由于浮点数的精度问题,输出结果为“Not Equal”。

示例 2:累加误差

#include <stdio.h>int main() {float sum = 0.0f;for (int i = 0; i < 10000; i++) {sum += 0.0001f;}printf("Sum: %f\n", sum);return 0;
}

在这个示例中,预期的结果应该是 1.0,但由于累加过程中的精度损失,实际输出的结果会小于 1.0。

示例 3:正确的浮点数比较

#include <stdio.h>
#include <math.h>int main() {float a = 0.3f;float b = 0.29999999f;const float epsilon = 0.0001f;if (fabs(a - b) < epsilon) {printf("Approximately Equal\n");} else {printf("Not Approximately Equal\n");}return 0;
}

通过定义一个较小的误差范围 epsilon ,并使用 fabs 函数计算两个浮点数的差的绝对值,然后与误差范围进行比较,来判断两个浮点数是否近似相等。

六、总结

C 语言中的浮点数精度问题是由于其存储方式和有限的位数导致的。在编程中,需要充分认识到这些问题可能带来的影响,如数值比较的错误、算术运算的偏差和累计误差等。通过选择合适的数据类型、采用正确的比较方法、优化算法和注意数值范围,可以有效地减少浮点数精度问题带来的潜在错误,提高程序的正确性和可靠性。


分割线

🎉相关推荐

  • 📙C 语言百万年薪修炼课程 【https://dwz.mosong.cc/cyyjc】 通俗易懂,深入浅出,匠心打磨,死磕细节,6年迭代,看过的人都说好。
  • 🍅博客首页-关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!
  • 📙CSDN专栏-C语言修炼
  • 📙技术社区-墨松科技

分割线



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

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

相关文章

matlab支持向量机使用错误

&#x1f3c6;本文收录于《CSDN问答解答》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&…

ROS的TF系统

一、SLAM 1、SLAM全称是Simultaneous Localization And Mapping&#xff0c;即同时定位与地图构建 2、SLAM软件包Hector_Mapping&#xff0c;←建图可参考链接所示文章 二、机器人定位 1、假设机器人开始建图的位置是地图坐标系的原点 2、则机器人在建图过程中的位置可以描…

DenseNet算法实现乳腺癌识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、前期准备 1.设置GPU import torch import torch.nn as nn import torchvision.transforms as transforms import torchvision from torchvision import …

CUDA原子操作

代码 #include <cuda_runtime.h> #include <stdio.h>__global__ void atomicAddAndGet(int *result, int *valueToAdd) {// 原子加法int addedValue atomicAdd(result, *valueToAdd);// 通过原子操作后读取值&#xff0c;确保是加法后的值addedValue *valueToAd…

黑马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录 Day4

你好,我是Qiuner. 为帮助别人少走弯路和记录自己编程学习过程而写博客 这是我的 github https://github.com/Qiuner ⭐️ gitee https://gitee.com/Qiuner &#x1f339; 如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 &#x1f604; (^ ~ ^) 想看更多 那就点个关注吧 我会…

HDFS Decommission节点的长尾分析和问题解决

文章目录 前言Decommission过慢的分析过程NameNode页面并不显示Decommission的进度和剩余块数量增加每次调度的块数量增加Stream Limit以避免节点被Skip节点被Skip时应该在DEBUG时打印原因在大量节点被Skip的时候加快有效调度其他可能改进 基本流程解析用户通过节点刷新触发Dec…

java Web学习笔记(一)

文章目录 1. 前置学习知识2. Tomcat介绍Tomcat目录文件介绍URL的组成部分和项目资源的对应关系idea配置部署tomcat并成功运行一个app-web项目 3. HTTP协议介绍&#xff08;很重要&#xff09;HTTP协议和HTTPS的区别HTTP协议的发展理解HTTP协议 报文格式报文响应的状态码 4. Ser…

以设备为核心的状态自动采集、人工运维和预测性维护为一体的智能管理系统

中服云设备全生命周期管理系统充分利用物联网、人工智能、机器学习、大数据等新一代技术&#xff0c;实现对企业生产设备从采购、安装、调试、使用、维护、维修、改造、更新直到报废全生命周期的智能化、数字化、可视化的实时管控&#xff0c;支持设备运行状态的自动采集和人工…

js 中 new Worker 报错 Failed to construct ‘Worker‘

new Worker("worker.js");运行多线程 Web Worker 的时候报错 Uncaught DOMException: Failed to construct ‘Worker’ 原因是浏览器不允许通过本地文件访问使用Web Worker。 解决方法&#xff1a; 将项目部署到服务器上或者用Node起本地服务访问项目

活动回顾|矩阵起源2024WAIC圆满落幕

2024年7月4日至7日&#xff0c;全球瞩目的2024世界人工智能大会暨人工智能全球治理高级别会议&#xff08;WAIC 2024&#xff09;在上海盛大举行&#xff0c;其中Future Tech 100未来之星创新孵化展再次成为大会焦点&#xff0c;它不仅是一场科技成果的展示&#xff0c;更是全球…

网络通信基本知识

网络通信 什么是网络通信&#xff1f; 通信网络是指将各个孤立的设备进行物理连接&#xff0c;实现人与人&#xff0c;人与计算机&#xff0c;计算机与计算机之间进行信息交换的链路&#xff0c;从而达到资源共享和通信的目的。 什么是网络协议&#xff1f; 网络协议是计算机…

SPring Boot整合第三方框架

springboot整合第三方框架 1. 整合mybatis 1.1引入依赖——pom.xml配置文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instanc…

安装isce2

今天再次尝试安装&#xff0c;之前试过2次都是卡在同一步&#xff0c;今天换成了用mamba conda就没有再报错了 全程参考云军老师的step by step教程&#xff0c;安装成功 GitHub - yunjunz/conda-envs: conda environment setup on Linux / macOS for InSAR data processing …

【进阶】利用python内置模块自动化发送邮件及邮件附件

目录 自动化发送邮件 流程&#xff1a; 步骤&#xff1a; 【重点】 【MIMEText--发送文本类型的邮件】 【MIMEImage-发送附件为图片的邮件】 【MIMEBase--发送附件为html报告的邮件】 自动化发送邮件 以qq邮箱为例&#xff0c;提前打开POP3/IMAP/SMTP/Exchange/CardDAV 服…

【Redis】复制(Replica)

文章目录 一、复制是什么&#xff1f;二、 基本命令三、 配置&#xff08;分为配置文件和命令配置&#xff09;3.1 配置文件3.2 命令配置3.3 嵌套连接3.4 关闭从属关系 四、 复制原理五、 缺点 以下是本篇文章正文内容 一、复制是什么&#xff1f; 主从复制 master&#xff…

GloVe: Global Vectors for Word Representation论文笔记解读

基本信息 作者Jeffrey Penningtondoi10.3115/v1/D14-1162发表时间2014期刊EMNLP网址https://aclanthology.org/D14-1162.pdf 研究背景 1. What’s known 既往研究已证实 全局矩阵分解方法&#xff1a;LSA&#xff0c;考虑整个语料库词频的统计信息得到共现矩阵&#xff0c;通…

根据视图矩阵, 恢复相机的世界空间的位置

根据视图矩阵, 恢复相机的世界空间的位置 一、方法1 glsl 实现: // 从本地局部坐标系(相机空间) 到 世界空间的旋转变换 mat3 getLocal2WorldRotation() {mat3 world2localRotation mat3(viewMatrix[0].xyz,viewMatrix[1].xyz,viewMatrix[2].xyz);return inverse(world2loca…

汽车零配件行业看板管理系统应用

生产制造已经走向了精益生产&#xff0c;计算时效产出、物料周转时间等问题&#xff0c;成为每一个制造企业要面临的问题&#xff0c;工厂更需要加快自动化&#xff0c;信息化&#xff0c;数字化的布局和应用。 之前的文章多次讲解了企业MES管理系统&#xff0c;本篇文章就为大…

论文er们,YOLO这口饭得趁热吃

不知道各位有没有看出来&#xff0c;从去年开始YOLO相关的论文就处于一个井喷式状态&#xff0c;SCI各区都能见到它的身影。 这是因为YOLO其实是个很好发论文的方向&#xff0c;需求量很大&#xff0c;热度高&#xff0c;并且好入门&#xff0c;能获取的资源也很多。写论文时一…

宾馆酒店电视信号高清改造-广电信号接入数字电视同轴高清传输系统应用

宾馆酒店电视信号高清改造-广电信号接入数字电视同轴高清传输系统应用 由北京海特伟业科技有限公司任洪卓发布于2024年7月12日 一、宾馆酒店广电信号接入数字电视同轴高清传输系统建设背景 在当今数字化快速发展的时代&#xff0c;宾馆酒店作为服务行业的重要组成部分&#x…