摘要 计算机的错误计算(一)介绍了算术表达式的错误计算。本文介绍循环迭代程序的错误计算。
例1. 1989年, 法国学者Muller在其著作《计算机算术》中给出了一个循环迭代:
它收敛于6。然而,它在任何系统任何精度下均出错:它总是趋向100,而不是正确答案6。比如,若用下面图1中代码计算,
图1 一个C程序,它使用双精度计算的值
则在基于Pentium 4 的工作站(Linux系统,Gcc)上的几个输出结果为
它表明:从开始,程序的输出结果中不再含有正确有效数字;并且从
开始,结果就非常接近于100。
例2. 2004年,被称为“浮点之父”的图灵奖获得者Kahan又给出了例1中迭代的一个变形:
对于该变形,同样,若直接编程,则任何机器均得不到正确结果5。比如,若在Intel 302上使用FORTRAN语言编程计算,则扩展精度下,从开始,结果均为100。
问题来了:上述两个错误案例是偶然的吗?仅有的吗?不是的。可以轻易产生一个计算机会算错的案例吗?答案是:可以!
比如,随机取2个数(一大一小):200,12.3。这时,它们的和为212.3,积为2460。构造下列迭代:
容易验证,理论上,其每一次迭代的值均等于初值12.3。然而,若用C语言编程,则在Gcc 4.9.2与Visual Studio 2010的环境下,分别从与
开始,不再含有正确的有效数字。
从上述分析可以得出,产生错误输出结果的循环迭代程序存在无数个。
那么,出错原因是什么呢?很明显,误差的积累与传播导致了错误结果。
实际上,我们可以将视野放得更宽,想一想具有蝴蝶效应的(混沌)系统:微小的输入变动可能导致预测结果大幅偏差的系统。这样的系统有多少个呢?有无数个。
比较简单的一个案例是余切序列 。不论初值取 1、2、3或100,或1000等等,均会出现错误结果。并且,错误是在
并不很大的情形下出现。
最后总结一句:目前,不论是C++,或是Java,或Python,或其它语言,循环程序均可能输出错误结果。
文中内容或涉及的文献请参考:
[1] 赵世忠, 陈冬火, 刘静. 循环迭代程序的一种可信计算算法. 软件学报, 2020, 31(12): 3685-3699
补充一点:对于一层循环程序,可以通过 ISReal --- 程序病态模型检验器 检查其是否会输出错误结果。