计算机的错误计算(二)

摘要  计算机的错误计算(一)介绍了算术表达式的错误计算。本文介绍循环迭代程序的错误计算。

例1. 1989年, 法国学者Muller在其著作《计算机算术》中给出了一个循环迭代:

\left\{ \begin{array}{ll} u_1=2, & \\ u_2=-4, & \\ u_n=111-\displaystyle{\frac{1130}{y_{n-1}}+\frac{3000}{y_{n-1}y_{n-2}}}. & \end{array} \right.

它收敛于6。然而,它在任何系统任何精度下均出错:它总是趋向100,而不是正确答案6。比如,若用下面图1中代码计算,

图1  一个C程序,它使用双精度计算u_n的值

则在基于Pentium 4 的工作站(Linux系统,Gcc)上的几个输出结果为

\left\{ \begin{array}{ll} u_{17}==7.2356654170119432, & \\ u_{20}=98.350416551346285, & \\ u_{30}=99.999999999998948. & \end{array} \right.

它表明:从u_{17}开始,程序的输出结果中不再含有正确有效数字;并且从u_{20}开始,结果就非常接近于100。

例2. 2004年,被称为“浮点之父”的图灵奖获得者Kahan又给出了例1中迭代的一个变形:

\left\{ \begin{array}{ll} y_1=4, & \\ y_2=4.25, & \\ y_n=108-\displaystyle{\frac{815}{y_{n-1}}+\frac{1500}{y_{n-1}y_{n-2}}}. & \end{array} \right.

对于该变形,同样,若直接编程,则任何机器均得不到正确结果5。比如,若在Intel 302上使用FORTRAN语言编程计算,则扩展精度下,从y_{32}开始,结果均为100。

       问题来了:上述两个错误案例是偶然的吗?仅有的吗?不是的。可以轻易产生一个计算机会算错的案例吗?答案是:可以

       比如,随机取2个数(一大一小):200,12.3。这时,它们的和为212.3,积为2460。构造下列迭代:

\left\{ \begin{array}{ll} y_1=12.3, & \\ y_n=212.3-\displaystyle{\frac{2460}{y_{n-1}}}. & \end{array} \right. 

容易验证,理论上,其每一次迭代的值均等于初值12.3。然而,若用C语言编程,则在Gcc 4.9.2与Visual Studio 2010的环境下,分别从y_{14}y_{15} 开始,不再含有正确的有效数字。

       从上述分析可以得出,产生错误输出结果的循环迭代程序存在无数个。

       那么,出错原因是什么呢?很明显,误差的积累与传播导致了错误结果。

       实际上,我们可以将视野放得更宽,想一想具有蝴蝶效应的(混沌)系统微小的输入变动可能导致预测结果大幅偏差的系统。这样的系统有多少个呢?有无数个。

       比较简单的一个案例是余切序列 x_n=\cot(x_{n-1})。不论初值取 1、2、3或100,或1000等等,均会出现错误结果。并且,错误是在 n并不很大的情形下出现。

       最后总结一句:目前,不论是C++,或是Java,或Python,或其它语言,循环程序均可能输出错误结果。

      

文中内容或涉及的文献请参考:

      [1] 赵世忠, 陈冬火, 刘静. 循环迭代程序的一种可信计算算法. 软件学报, 2020, 31(12): 3685-3699

补充一点:对于一层循环程序,可以通过 ISReal --- 程序病态模型检验器 检查其是否会输出错误结果。

  • 18
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值