语言的细节决定了一种语言到底是可靠的还是容易滋生错误的。1961年夏天,一名NASA(美国航空航天局)的程序员戏剧性地向世人展示了这一点。他测试一个用于计算环绕地球轨道的Fortran子程序。这个子程序已经数次用于简短的Mercury飞行,但它的计算结果总是达不到预期的精度,无法满足更外层的太空飞行和登月计划。计算结果非常接近,但与预期的精度相比还是有一定的距离。 经过漫长的对算法、数据和预期结果的检查之后,这名工程师最终注意到了下面这行代码: Do 10 I = 1.10 显然,程序员的原意是想编写下面这样的循环: Do 10 I = 1,10 在Fortran中,空白字符没有什么意义,它们甚至可以在标识符的内部出现。Fortran的设计者的初衷是这样可以避免因打卡机的振动而产生的错误,提高程序的可靠性。所以,你可以使用像MAX Y这样的标识符。但不幸的是,编译器自作聪明地把上面这条语句理解成: Do10I = 1.10 在Fortran中,变量无需声明即可使用。在上面这条语句中,1.10被赋值给隐式声明的浮点型变量Do10I。这条语句位于一个循环结构中,但它只实行了1次而不是预期的10次。它只是在第一次给出一个近似值,而不是通过迭代法逐步求精。把句号改成逗号后,计算结果的精度就与预期的相符了。 这个Bug发现得早,因此并不像许多人声称的那样曾经导致Mercury太空飞行失败(Mariner飞行项目中的另一个Bug,确实导致了这个后果)。 Mariner也跟一个戏剧性的App失败有关,但它的行为大不相同,而且跟语言的选择也毫无关系。Mariner于1962年7月发射,它的任务是将一个探测器放在金星上。但在发射后几分钟,地面控制中心就不得不将它摧毁,因为发射它的Atlas火箭开始偏离轨道。 经过几个星期的分析,问题被确定出现在App中。但它是一个算法上的抄写错误而不是一个程序的Bug。换句话说,程序严格按照程序员的设想实行,但在说明书上,指令本身却存在错误!跟踪程序被确定为操作平滑(平均)的速度。在数学中,在变量符号上面加个水平的“ ̄”符号表示求平均,在提供给程序员的手写制导方程式中,这个“ ̄”不小心被漏掉了。 那个程序员正确的按照算法编写了程序,并使用了从雷达指引的原始速度而不是平均速度。结果,程序觉察到了火箭速度的微小波动,在经典的负反馈循环中,它试图调整火箭的速度,但在这个过程中却出现了真正的不稳定行为。这个有缺陷的程序曾用于以前的几个任务中,但这个程序确实第一次实行。在以前的几次飞行中,火箭的飞行是由地面控制的,但在这一次,由于天线故障使它无法接收到无线电指令,因此使用了飞船上的控制App。
|