1991年2月25日, 在海湾战争中,位于沙特多哈的一个爱国者导弹防御系统没能成功拦截一枚来犯的萨达姆导弹。结果导弹击中军营,导致28名士兵死亡,98人受伤。在
控制软件中的一个错误产生了自系统启动以来时间的不正确的计算结果,这是由于实数的不精确的二进制表示所造成的舍入错误累积所致。
一连串的计算中的舍入错误可能累积的非常大,以至于计算结果和正确的值相差太远。
这个系统的时钟度量的时间是通过乘以0.1来得到以十分之一秒的计算时间。
和大多数十进制小数一样,0.1的二进制表示是无穷的:
(0.00011001100110011001100110011001100110011...)2
而爱国者导弹中的24位寄存器只存储了这个数的近似值,
(0.00011001100110011001100)2
这是一个大约0.000000095的误差。 这个系统在此期间已经运行了大约100小时,舍入错误的累积大于0.34秒。
而在这个时间中以1700米每秒的速度飞行的萨达姆导弹可以飞行大约580米,这意味着计算得到的位置与实际位置差了500多米。
有时就是这种小错误导致大损失。
for (double i = 0; i != 5.0; i += 0.1)
cout << i << endl;
如果你运行上面代码你会发现这是一个死循环, 因为 i 永远不会等于5.0 。 你可以调试来看看i究竟等于多少。
为了避免这种错误
可以把 i != 5.0 改为 i <= 5.0
上面说的可能很多人都知道。
说这些只是为了说明,有时一个小小的编程错误会导致很严重的结果。 所以大家一定要用心完成这神圣的工作。
还有很多软件失误导致的事故:
1999年9月火星气候探测卫星一同撞入了这个行星中。NASA调查结果是一个基于地面的和导航相关的
任务软件的某个部分没能正确地将火箭推力从英制单位转换为公制单位。
1996年6月,欧洲太空署花费70亿美元开发的一枚遥控阿里亚5型火箭在发射37秒后,于其处女飞行中发生爆炸。调查结果是由于
软件需求规格说明和设计错误所致的。 还发生了因为将64位浮点数转化为16位浮点数而运行错误。
1991年3月,DSC通信公司给它的贝尔客户发送了一个用于高电容电话路由和交换系统的产品升级
软件。在这个夏天使用了这个系统的地区导致大规模电话停机。造成这种情况的原因是信号软件中的一个错误。在这个软件的数百万行代码中,有三行被修改了,而这个公司认为没有必要重新测试程序。
有时这就叫做
蝴蝶效应吧...
—— 引用自Larry Nyhoff的
《ADTS, DATA STRUCTURES, AND PROBELM SOLVING WITH C++》
没有经过他老人家允许就用了他的文字有点罪过......