当前位置: 首页 > news >正文

[技术讨论] 【C语言实战经验4】浮点数运算,你踩过什么坑

在C语言的浮点数运算(包括float和double两种浮点数据类型)方面,你踩过什么坑?
有没有朋友曾经遇到过或解决过因浮点数运算操作不当引起的Bug?在解决的时候,是否还很疑惑为什么不能这样操作浮点数?
前几年参加软件培训时听过的一个因浮点数的特殊性造成的军事问题,与大家分享:
1991年2月25日,在海湾战争的时候,美国爱国者导弹由于拦截伊拉克飞毛腿导弹失败,导致美国一个兵营近28人死亡。
那为什么会拦截失败呢?原因是这样的:
爱国者导弹的软件系统里内置了一个计数时钟,每隔0.1秒计数加1,为了以秒为单位来确认时间,软件代码里用一个24位的近似于1/10的二进制小数值与计数器值相乘。我们知道,计算机中的1/10的二进制其实是一个以0011为无限循环的无穷序列:0.000110011[0011]……,而计算机中仅用序列的开头位和二进制小数点右边的23位来近似表示0.1,那么其与0.1之间的差值就是:0.000000000000000000000001100[1100]……,即2-20*1/10 = 9.54*10-8秒;因此,如果从系统启动开始计算,时钟从0开始,且一直保持计数,如果按系统运行100小时后计算,实际时间就会相差0.0343秒,按导弹速度2000米/秒计算,那距离就相差68.7米。所以,因为距离偏差就导致了拦截失败。
上面这个新闻可能是真实的也可能是虚构的,但这不是我们关注的重点;
我们关注的重点是出现以上严重军事问题的原因是浮点数的精度问题。
我们再来看看浮点数0.1的输出打印情况:
备注:以下所有代码测试都基于64位系统,并在Visual C++ 6.0软件上实现。

为什么输出打印结果是0.100000,主要还是因为浮点数的二进制表示存在精度问题。
浮点数在计算机中是基于二进制存储的,而大多数十进制小数无法被二进制准确表示,因此会存在精度损失。例如,0.1在二进制中是一个无限不循环的小数,即0.1 (十进制) = 0.00011001100110011… (二进制)。在float类型中,只能存储23位小数部分,因此0.1会被截断并转换成一个近似值。
在打印浮点数时,打印函数会根据标准进行舍入和近似处理,尽可能使近似值接近原值,称为“最良近似值”‌1。因此,尽管0.1的精确二进制表示无法完全存储在float中,但在打印时通常会展示一个接近原值的近似值,如0.100000。
所以,0.1无法被精确存储,实际可能是0.100000或0.100000001或其他值。

另外,这种精度问题不仅限于0.1,其他小数如0.2和0.3在进行运算时也会因为二进制表示的限制而出现精度损失,即0.3-0.2的结果在打印时并不是0.1:

另外,在程序代码中也尽量不要直接进行浮点数的相等或不相等比较,这样可能会导致不精确的结果;
可以定义误差范围(阈值),并使用绝对误差的代码方式进行比较:


类似地,判断一个浮点数是否为零的时候,可以按如下两个方法进行
使用近似比较:


使用标准C库函数isnormal:


备注
对于C99及更高版本,可以使用isnormal函数来判断一个浮点数是否为非零且在标准范围内(即不是无穷大、NaN或零)。
此外,再说明一个在类型转换运算时需要注意的地方,直接展示代码执行结果:


从以上代码及其执行结果可以看出,浮点数在执行类型转换时是需要显示转换的,或者可以使用浮点数常量(如1.0),以避免在代码量多时就不容易找出问题所在的情况。
因此可以得出以下结论:
并非所有的浮点数都能够在计算机中使用二进制来完全表示;
计算机中对浮点数执行运算时,很有可能会产生舍入和截断;
并非所有的浮点比较都会出现错误,但是参与运算的浮点数就很容易出现误差,甚至极小的误差在被长时间放大后,由于累积误差,也会带来意想不到的严重后果。
所以,在C语言中操作浮点数,一定要记住:
不要直接对浮点数进行相等或者不相等的比较;
在判断浮点数是否为零时,需要通过类似于浮点数<=阈值来判断,阈值大小视情况而定;
循环控制表达式不应该包含有浮点数类型;
如果程序代码涉及浮点数,你一定要格外小心再小心;
使用浮点数来存储小数是不能得到精确值的,如果有高精度要求,可以考虑使用定点数或者高精度库(比如高精度浮点运算库GMP)。
如果你有更多关于C语言浮点数运算方面的踩雷经历和避坑技巧,欢迎来贴分享!
让我们一起进步,变的更加优秀。


---------------------
作者:dffzh
链接:https://bbs.21ic.com/icview-3454552-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

http://www.rkmt.cn/news/175504.html

相关文章:

  • MSVBVM50.DLL文件丢失损坏找不到 打不开程序问题 下载方法
  • DiskInfo工具监控GPU磁盘使用情况(配合PyTorch镜像)
  • 2025年行业内优质的干燥设备厂家怎么选择,JFG-C系列高效沸腾干燥机 /多功能动态干燥机厂家口碑推荐 - 品牌推荐师
  • [应用方案] GALT62120_尾灯自动单 LED 短路 (AutoSS) 检测功能的问题与理解
  • 2025环保纸杯创业指南:全自动生产线核心设备盘点——从纸杯机、纸碗机到杯盖机的制造商全景解析 - 品牌2026
  • 菜鸟无忧聚焦央国企求职:专业陪伴如何助力大学生职业能力成长 - 博客万
  • 10422_基于Springboot的教务管理系统
  • 震惊!大模型Agent开发终极指南:从小白到大神的进阶之路,代码不会?看完秒变“Agent大神“!这波必须上车!
  • AI工程化实战《八》:RAG + Agent 融合架构全解——打造能思考、会行动的企业大脑
  • 2026年跨境业务GEO源码 支持多语言多币种适配 - 源码云科技
  • 项目分享|SoulX-Podcast:打造具有方言与副语言多样性的真实长音频播客
  • 2025西南、川渝最新防火玻璃厂家 TOP5 评测!四川、成都、西安等地区优质生产厂家及品牌权威榜单发布,守护建筑安全新高度 - 全局中转站
  • 麦弗逊悬架硬点布置程序:基于Matlab平台的计算与匹配
  • 2025年防火堵料加工厂哪家价格合理、服务周到排行榜 - 工业品牌热点
  • 2025年切捆条机来图定制推荐,切捆条机定制与优质服务厂家全解析 - 工业设备
  • 四川高杆路灯哪家的产品节能环保?哪家制造厂技术强? - myqiye
  • 燃烧试验机知名品牌盘点:国内外优质供应商怎么选? - 品牌推荐大师
  • 2025年高口碑烫金机品牌全解析,助您精准选择,国内烫金机厂家解析品牌实力与甄选要点 - 品牌推荐师
  • 收藏!AI会砸程序员饭碗?小白资深开发者必看的破局指南
  • 2025湖里装修公司口碑指南:这10家高性价比企业闭眼选 - 品牌测评鉴赏家
  • 2026 年工作计划 PPT 框架怎么搭?AI 一步完成
  • excel接入deepseek 实现周报自动生成
  • diskinfo下载官网替代方案:通过PyTorch镜像监控GPU存储
  • 連續處理10億條記錄,記憶體零增長:Python迭代器與記憶體重用黑魔法
  • DDR4基础扫盲(二)
  • 收藏!为什么程序员必须懂大模型?2025入门必备指南
  • 2025西南、川渝最新防火隔断厂家 TOP5 评测!四川、成都、西安等地区优质品牌及生产厂家权威榜单发布,守护建筑安全新生态 - 全局中转站
  • Jupyter Notebook直连PyTorch-GPU环境操作教程(附截图)
  • git submodule管理子模块:与PyTorch-CUDA-v2.7协同开发
  • 全球金融数据实时对接实战:基于WebSocket的印度、马来西亚、韩国股票API集成指南