阐述 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,一经查实,立即删除!

相关文章

从零开始学习嵌入式----C语言函数指针

C语言的函数指针&#xff1a;从入门到深入理解 函数指针是C语言中一个强大且灵活的特性&#xff0c;它允许我们将函数作为参数传递给其他函数&#xff0c;或者将函数存储在数据结构中。正确理解和使用函数指针可以帮助我们编写更加模块化、高效和可扩展的代码。 一、 什么是函数…

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…

java word转pdf、word中关键字位置插入图片 工具类

java word转pdf、word中关键字位置插入图片 工具类 1.pom依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.15</version></dependency><dependency><groupId>org.apa…

重读AI金典算法模型-GPT系列

2023年对于AI来说&#xff0c;可以算是一个里程碑式的年份&#xff0c;随着OpenAI的chatGPT的大火&#xff0c;遍地的生成式AI应用应运而生。在这些上层应用大放异彩的时候&#xff0c;我们需要了解一些底层的算法模型&#xff0c;并从中窥探出为什么时代选择了OpenAI的chatGPT…

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

中服云设备全生命周期管理系统充分利用物联网、人工智能、机器学习、大数据等新一代技术&#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起本地服务访问项目

Pandas数据持久化秘籍:to_pickle()函数的高效应用与实战技巧

Pandas数据持久化秘籍&#xff1a;to_pickle()函数的高效应用与实战技巧 引言 在数据分析和机器学习的项目中&#xff0c;数据的持久化存储和快速加载是一个重要环节。Pandas作为Python中广泛使用的数据处理库&#xff0c;提供了强大的数据结构和操作功能。其中&#xff0c;t…

活动回顾|矩阵起源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 服…

Linux vim编辑器常用知识

Vim 是 Linux 中一个强大的文本编辑器&#xff0c;以其高效的键盘操作和丰富的功能而闻名 Vim 的基本概念 模式&#xff1a;Vim 有三种主要模式&#xff1a; 普通模式 (Normal Mode)&#xff1a;默认模式&#xff0c;用于浏览和编辑文本。插入模式 (Insert Mode)&#xff1a;用…