|程序员应知应会之二进制小数的计算
作为一名程序员 , 大家都知道计算机里的数字都是用二进制来表示的 。 那么具体是怎么表示的 , 很多人可能就不太清楚了 。 毕竟大家都已经习惯了定义一个float或double就觉得万事大吉了 。 然而虽然通常情况下这样并不会出什么问题 , 但是在特殊的情况下 , 还是有可能出问题的 。
例如在1991年2月25日 , 第一次海湾战争期间 , 美国设置在沙特阿拉伯达摩地区的爱国者导弹 , 在拦截伊拉克的飞毛腿导弹的过程中 , 就因为一个底层数字的计算不精确 , 导致拦截失败 , 最终飞毛腿导弹击中了美国的一个兵营 , 造成了28名美军士兵的死亡 。 事后 , 美国总审计局对失败原因进行了详细的分析 , 最终定位到底层的原因就是在为一个数字精度的问题 。
【|程序员应知应会之二进制小数的计算】
下面我们先来看看小数在二进制里是怎么表示的 。 二进制小数在浮点型数字里面 , 以0.101的形式表示 , 二进制小数点向右移动一位相当于将该数乘2 , 向左移一位相当于将该数除以2 。 因此二进制数101.11表示5.75 。 1011.1相当于11.5 。
了解了这些以后 , 我们再回过头来看下前面那个爱国者导弹的问题 。 经过调查分析 , 爱国者导弹中有一个内置的时钟 , 其实现类似于一个计数器 , 每隔0.1秒就加1 。 因为时间计数是以秒为单位的 , 所以程序用了一个24位近似于十分之一的二进制小数来乘以这个计数器的值 。 因为0.1的二进制是一个无限循环小数0.000110011[0011...
, 对于24位的二进制数来说 , 只需要考虑二进制小数点右边的前23位 , 即0.00011001100110011001100 。 那么真实的0.1与真值之间的误差即为0.1减去这个数 , 这个误差约为0.0000000954 。
而在出错的爱国者导弹发射之前 , 系统已经运行了100小时 , 那么因为这个时钟的偏差就已经达到了0.0000000954*3600*100 , 约为0.343秒 。 而飞毛腿导弹的速度为2000米/秒 , 那么误差距离即为2000*0.343 , 达到686米 。 因此导致拦截失败 。
由此可见 , 如果不深入了解计算机系统的具体实现 , 就会在工作中出现意想不到的后果 。 甚至出现灾难性的后果 。
现在中国已经很多年没有打仗了 , 一旦打仗 , 暴露出来的系统问题可能会比美国多得多 。 到时候 , 不知道会有多少解放军战士会因为信息系统的开发者的专业能力问题而白白牺牲 。
- 5G|一个月 5000元 的公务员和一个月 15000元的程序员,你会选择哪一个?
- 程序员|在不久的将来,软件程序员是否将成为与低薪劳动者一样的情况?
- 程序员|全球首次!华科夺冠
- 键盘|程序员画 2000 元买两个一模一样的键盘,这种心理你会认同
- 程序员|不同城市程序员中位数工资都是多少?
- 程序员|如何健康学习到150岁?养生还是程序员专业
- 程序员|寒冬来了!腾讯、阿里、美的开始过苦日子,普通人何去何从?
- 上能写代码,下要“揍”黑客,还有什么不是程序员的“锅”?
- 程序员|我,杭州的程序员,透露年薪,告诉你工作经历如何,月花销有多少
- 程序员|程序员45岁之后,绝大部分都被淘汰吗?真相寒了众人的心