在前一篇文章中我们已经了解到了牛顿迭代法的基本原理,在现在,我们就要将其编写为程序。
为了实现输入一个方程,给出其解的目标,我们需要一个能计算出字符串表达式的结果的函数,这个函数功能我在之前的文章中已经完成了,请参看[这里],在今天的代码中,我们默认Compute函数是已经定义完成的。
首先,我们需要简化我们要解决的问题:
输入一个一元方程,给出解。
对于一元方程而言,只有一个未知数,那么我们目前姑且认为这个未知数的符号就是小写的“x”,实际上我们从[上一篇文章]中就能了解到,我们只用考虑在x的估计值上的函数和导函数的值即刻,也就是说,在处理这个问题的时候,这个方程中的x,只要根据需要被替换为要带入的数值,就可以直接计算了。
方程的形式多种多样,但我们总能将其转化为F(x) = 0的样子,比如f(x) = g(x),只需要把等号改为减号,我们就能得到这个方程的整齐样式,这样我们再带入数值的时候,只需要计算f(x) – g(x)的结果,就可以了。
在处理这个问题上,我们使用的方法很简单:

1.找到等号,替换为“-(”
2.在方程的最后再添加“)”

你能理解上面这两个步骤的意义吗?直接把等号改为减号,g(x)一旦是多项式,就会导致符号的混乱,为了避免这种混乱,我们直接加上括号,是不是非常方便?
这个步骤我们称为“预处理”,因为之后的带值运算,都只需要这一操作后得到的那个字符串,而不再需要原始方程。
这里给出代码:

然后我们还要做的就是实现一个计算f(x0)的值的功能函数,也就是我之前所提到的“带入求值的过程,说白了,就是一个非常简单的字符串替换,把x替换为一个数字字符串(这里需要把double型的浮点数字转换为字符串),不多废话,看代码你就能明白了:

在进行牛顿迭代运算之前,我们还有一个急需解决的问题,那就是导函数如何求得?在已知函数表达式的情况下,导函数是可求的,但是符号运算本身就是相当复杂的工作,对于通过符号运算求出函数的导函数表达式,不是不可以,而是太复杂,对于这个问题,我之前在看“几何画板”的帮助的时候注意到了一个快速求导数值的公式,其实就是利用了导函数的定义“近似地”获取一个导函数的值,而且通过这种方法计算获得的值精确度非常高:

这样我们只需要用到我们之前的“代值”操作以及原函数表达式就可以求出表达式的值了,由于整个过程是“一句话代码”,故我们采用内联函数的写法,不过由于现在编译器的进步,很多编译器对于这样的函数会直接优化为内联函数,所以这里不必深究,看代码:

最后就是我们求解函数的编写了,可以说,在做了上面准备工作之后,这个迭代求解的过程简直弱爆了,这里有一点需要注意,绝对值函数如果是用C语言的话,使用的是absf函数,但是我们整个程序都大量使用了C++的标准模板库,所以不用C++的话应该都是编译不能的,这个求解函数要求输入一个近似根的估计值,通常来说这个值可以随便取(我默认取的是0.01,为了错开一些常见函数的无定义域),这个值取的好坏有时会影响迭代的速度、收敛的方向(比如多次函数的多解,该迭代法只能找到与第一估值点同单调性的一个区间内的点):

对于现在这个程序而言,你只需调用Solve函数就可以求解一个字符串表达的方程了。当然程序还有改进的空间,比如未知数可以是自己的定义,再比如在求解过程中,有可能出现无限次迭代的情况(比如一开始导函数就为0),对于这种“无解”的情况,应当做出特别的判断,这就留给读者自己思考和改进了:)。

3
说点什么

2 Comment threads
1 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
3 Comment authors
  Subscribe  
最新 最旧 得票最多
提醒
多元

多元代数方程又该怎么求呢

yoyowinwin

博客弄得很不错哦~~
代码也很靓