数与图(7)——求多项式的值
在上一篇《数与图(6)》中,我们实现了多项式的乘法,但是遗留了一个很重要的问题——如何验证程序的正确性呢?在这篇文章中,我们尝试给定一个x的值,用两种方法求多项式的值,即,同时将x的值带入乘积表达式:
及多项式表达式(上一篇文章的结果):
看看能否得到相同的值。
为了计算的方便,创建两个有返回值过程——多项式求积、多项式求和,代码如图1所示。
图1 有返回值过程:多项式求积与多项式求和
图1中显示了标签1的显示文本,也就是多项式乘法的题目和计算结果,如果程序没有错误,那么对于同一个x,这两个过程应该得出相同的结果,让我们来测试一下。
在连接了AI伴侣的情况下,完全可以脱离手机对程序进行测试,如图2所示。
图2 将x带入表达式求值
图2中显示的结果表明,两个过程对于同一个x,给出了不同的结果,这出乎了我的意料。显然,多项式求积的结果是不会有错的,出错的是多项式求和,而且可以断定我的程序有bug!
找bug是程序员的基本功,也是由新手成长为高手的必经之路。我盯着程序看了一会儿,猜想bug出在哪里。通常的思路是逆着程序执行的方向,从最靠接结果的地方开始查找,如图3所示。
图3 查找bug的思路
根据图3的思路,我们来实施步骤3)和步骤4),分别检查这两个过程,通常的方法是用最熟悉的数据进行测试,如(x+1)*(x+1),测试结果如图4所示。
图4 追踪错误的来源
由图4的结果推测错误发生在“合并同类项”过程里,那么事实是不是这样呢?将测试数据稍加改变,再来测试,如图5所示。
图5 将测试数据稍加改变得到不同的结果
由图5的测试结果推测,错误并非出自“合并同类项”过程,而是因为“双多项式乘积”过程给出的结果不符合要求。找到了问题的来源,就可以开始着手解决问题了。解决的办法是去掉多项式中最前面的加号。
创建一个有返回值过程——去除首项加号,代码如图6所示。
图6 有返回值过程——去掉首项加号
下面开始使用“去加号”过程,来测试此前的(x+1)*(x+1),测试结果如图7所示。
图7 运用去首项加号过程
接下来要改造此前的代码,对某些表达式实施“去首项加号”操作。首先要改造的就是“多项式乘积”过程,修改后的结果如图8所示。
图8 对输出的多项式结果实施“去首项加号”操作
值得注意的是,合并同类项过程是一个递归调用的过程,每次递归调用时,都要对中间结果作“去首项加号”操作,修改过的代码如图9所示。
图9 对递归调用过程的中间结果作“去首项加号”操作
经过上述修改,我们来测试一下结果,如图10所示。
图10 修改后程序的测试结果
我们依然不能确定这个结果就是正确的,所以下面要改造一下“多项式求和”过程,将其中的系数改为图10中的结果,并用求值法加以验证。修改后的代码及测试结果如图11所示。
图11 修改后的“多项式求和”过程及测试结果
图11显示的结果证明了我们对代码的改进是有效的。
文章写到这里,似乎已经到了尾声,完成了多项式的求值运算,并修改了原来程序中的bug,但是,我们并未对bug产生的机制进行讨论,为什么首项加号会导致合并同类项的错误,这个问题是值得思考的,希望喜欢探究的读者们自己来加以思考并找到问题的答案。