2026/2/9 21:34:12
网站建设
项目流程
cpa网站怎么做,微信管理系统平台,做视频网站对服务器要去,南宁广告网页设计招聘信息在C语言的浮点数运算#xff08;包括float和double两种浮点数据类型#xff09;方面#xff0c;你踩过什么坑#xff1f;有没有朋友曾经遇到过或解决过因浮点数运算操作不当引起的Bug#xff1f;在解决的时候#xff0c;是否还很疑惑为什么不能这样操作浮点数#xff1f…在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所有任何人未经允许禁止转载。