上一篇利用数学证明方式验证程序的可靠性(-),我利用一个例子说明利用数学方式证明的可能性。
其实,只要程序能够体现出算法,我们就能够利用数学的方式去证明。在算法教科书中也是利用数学方式去证明:数学归纳法来验证。
但是,为什么要利用数学方式来证明?其实我们最怕引进一个奇妙的方式,却给我们带来很大的麻烦(姑且说利用数学方式证明是奇妙的方式)。
因此这只是一个可选方式,但是数学方式的证明,却可以给我们的内心带来很大的安慰:因为问题抽象成数学方式,利用数学规则的证明是逻辑的、清晰的验证。这样可以让可靠性有很大的保证。或者是起码我们可以从逻辑上看到程序的可靠性。
如果没有逻辑上因果、一致的证明。我们只能靠压力测试,经验性的验证。难免内心会有一定的担忧。
其实,利用数学方式的证明,可以让我们逆向反推程序的bug。还是利用前一篇来介绍我的经验。
还记得前一篇文章提到的两段代码(呵呵,如果不记得没关系,我这里也要提及)。利用前一篇文章的证明那两段代码的可靠性方法。两段代码必须满足的数学条件:
代码(3)
(1)对于任意Ji,存在JCj_Nextpoll = Ji。
(2)对于数组下标k, k = (Cj_Nextpoll + i)%Max,如果i> 0,有Jk 后于JCj_Nextpoll被处理。Jk 为数组k下标对应的时间序任务。
对于代码(4)
(3)对于任意的Jk,Jk > JCj_Nextpoll,有
k = (Cj_Nextpoll + i)%Max,I > 0。
如果程序运行存在的现象与我们的预想不一致,我们可以根据这数学条件去审查代码。
在我写这篇文章的第二天,我到公司测试那个程序。结果在看日志的时候发现了Cj_Work的下标输出0,1,2,3. 结果又从0,1,2,3开始输出。
我利用那三个数学条件去审查代码,确保代码是没问题,但是令一地方的处理是有问题:
包含Cj_Work[max]的上一层变量重新被利用的机制。最后做了适当的修改,就解决了一个问题。
因此,我们可以利用这样的方式去寻找程序的bug。如果我们很明确的知道我们对程序的行为要什么结果,而这个结果必须满足哪些条件。这些条件分散在哪些代码中,再去反推。
如果利用前文介绍的方式,我们可以单独考虑某一些模块。因为那些模块只要尽责完成自己的任务就可以----------满足自己分担的条件。
哪一个模块没满足条件,问题大部分出现在那里。