应我们大一即将入坑的小萌新需求,想了解下浮点数的内容,所以本章将和大家讲讲浮点数的内容。
浮点数——说实在的,其应该可以归属于重要但非必要学习的内容,基本上的应用场景仅需记住浮点数不可做是否相等的判断即可。只有一些在不同平台上的浮点运算会出现一些取舍截断的问题,但是也可以用其他数值类型替代使用,如:用整数去替代浮点的运算,基于应用场景需求确定其精度,对整数做相应的乘除运算等等,这样不仅可以加快运行时间,更甚减少了精度丢失的风险。因为内容比较多,浮点数节将分两章介绍。首先将浮点数的由来、组成和经典案例,以加重大家的阅读与学习耐心,因为浮点数确实是比较有趣而无趣的。
1、浮点数的背景知识
在20世纪的80年代,每个计算机制造商都设计了自己的表示浮点数规则,以及对浮点数机器运算的标准。但是,他们不常常会关注运算的精确性,而把实现的速度和简便性看得比数字精确性更重要。当然啦,目前看来,这肯定是不被允许的,如若仍保持这种状态,那么浮点数的使用率肯定会逐步降低。所以大概在1985年时,随着IEEE标准754(这是电气和电子工程师协会-指定工业标准委员会)的推出,改变了这一现状,IEE754时一个仔细制定的表示浮点数及其运算的标准。
目前,所有的计算机都支持这个被称为IEEE浮点数的标准。大大的提高了科学应用程序在不同机器上的可移植性。
2、IEEE浮点表示格式
解:在最近通过与一些朋友沟通,发现目前部分的教学中,都不会太注重这个浮点数的解释,当然啦,老师带进门修行靠个人,但是个人认为当学生提出疑问时,作为一名教师,是有必要对学生进行答疑解惑的(纯属个人观点)。针对此类问题也可以理解,也包括业内大多数程序员朋友没可能都觉得浮点数没意思,往坏了说,深奥难懂。但是因为IEEE的格式定义在一组小而一至的原则上,所以它实际上时相当优雅和容易理解的。
如:
单精度 | ||
31 | 30 23 | 22 0 |
符号位(s) | 阶码(exp) | 尾数(f) |
双精度 | ||
63 | 62 52 | 51 0 |
符号位(s) | 阶码(exp) | 尾数(f) |
3、由于浮点数引起取舍精度导致拦截伊拉克飞毛腿导弹失败
浮点运算会引起一些匪夷所思的问题,浮点运算的运算不精确性能够产生灾难性的后果。如下历史故事就是惨痛的后果:在1991年2月25日,在第一次海湾战争期间,沙特阿拉伯的达摩地区设置的美国爱国者导弹,拦截伊拉克的飞毛腿导弹失败。飞毛腿导弹击中了美国的兵营,造成了28名士兵死亡。美国总审计局(GAO)对失败原因做了详细的分析,并且确定底层的原因在于一个数字计算不精确。
爱国者导弹系统中含有一个内置时钟,其实现类似一个计数器,每0.1秒就加1。为了以秒为为单位来确定时间,程序将用一个24位的近似于1*10的二进制小数值来乘以这个计数器的值。特别地,1/10的二进制表达式是一个无穷序列0.000110011[0011]........,其中,方括号部分是无限循环的。程序用值x来近似表示0.1,x只考虑这个序列的二进制小数右边23位:
x=0.00011001100110011001100。
假设:使用IEEE舍入到偶数的方式确定0.1的二进制小数点右边的23位的近似表示为y。
那么y应该为多少?
y = 0.00011001100110011001101
按照刚刚说的x的小数部分是无限循环1100的,所以可证明y比x大一点儿。
此时计算:
y-0.1 = 0.0000000000000000000000000[1100]
将y-0.1与1/10的二进制作比较,其值等于2^(-22)*1/10,约等于2.38*10^(-8)。
假设允许100小时后:2.38*10^(-8)*100*60*60*10≈0.086秒,爱国者导弹的误差是该值的4倍。
最后,一起来算算该程序对飞毛腿导弹位置的预测会偏差多少?
0.086*2000≈171米???????
什么概念?一个足球场长90—120米。
4、总结
相信通过上述内容,大家对浮点数会有深刻的印象了。本章的目的就是在于引起大家的好奇心,知道浮点数的重要性,而不是草草过之。下节将讲述浮点数的具体实现与小数的二进制互转的内容,以及具体实例作为参考,以便大家自行举例尝试。《C语言浮点数实现(二)》,因为内容较多,需要整理的信息也比较多,所以会慢一点,请大家见谅!!!