方程式求根
方程式解析解
想要获得方程式的解析解, 首先要能够明确表示方程的解析式. 表示方程式可以通过符号变量来实现, 符号变量是一种新接触的变量, 可以使用syms
或者sym
来定义.
1 | syms x % 定义符号变量 x |
成功定义后, 可以在工作区中发现一个新的变量x
, 其类型为 sym
中学数学教我们x+x+x
应该等于3x, 此处, 如果定义x是符号变量的话, 在matlab中输入x+x+x
也会得到一个3*x
的解析解.
1 | syms x |
其运算结果ans
的类型也是符号变量. 也就是说, 由符号变量导出的解析式的类型也是符号变量.因此对于解析式可以通过先定义符号变量x, 再输入方程关系式得到y.
1 | syms x |
下面正式介绍如何求方程式的解析解.
中学数学告诉我们, 求方程式的根与求函数零点问题是等价的, 因此一切方程式求根问题, 都可以转化为的问题. matlab中使用solve()
函数来求解函数的零点或者叫方程式的根. solve()
需要两个参数, 第一个参数输入函数解析式, 第二个参数指定哪个符号变量是自变量, 下面给出一些使用示例.
求 的根.
1 | %% 第一种方式 |
solve()
函数也可以用于方程组求解.
1 | syms x y % 定义x 和 y 两个变量 |
上述代码执行后, 在命令行窗口中给出如下答案:
我们可以在工作区中查看A的类型为结构体类型, 包括x 和y两个字段.
可以通过执行A.x
和A.y
来查看解的具体数值.
solve
函数不仅可以用于求解具体数值, 也可以用于求公式解.
求的公式解.
1 | syms x a b |
需要指出的是, 上面的代码中, solve
函数并没有指定哪个是未知数, 哪些是已知数. 在不指定哪个变量是未知数的情况下, 系统将默认x 是未知数. 如果我们把问题改成用a 和x 来表示b, 此时就需要在solve
函数中指出哪个是未知数.代码应该改为:
1 | syms x a b |
练习:
- 使用其他变量表示x :
- 求矩阵的逆矩阵.
参考代码:
1
2
3 %% 第一题
syms x a y b r
solve('(x-a)^2+(y-b)^2-r^2','x')运行结果:
1
2
3
4
5
6
7 syms a b c d A B C D
eq1=a*A+b*C-1;
eq2=a*B+b*D;
eq3=c*A+d*C;
eq4=c*B+d*D-1;
Ans=solve(eq1,eq2,eq3,eq4,'A','B','C','D');
[Ans.A Ans.B;Ans.C Ans.D]运行结果:
上一篇文章中学习了求微积分的数值解, 这里介绍一下求微积分解析式的函数. diff
在上一篇文章中介绍了其在处理向量时的作用, 在处理符号变量时, diff
将直接给出函数的解析式的导函数解析式.
求的导函数:
1 | syms x |
相对应的不定积分的求法使用int()
函数.
求
1 | syms x; y = x^2*exp(x); |
练习:
计算导数.
计算定积分.
参考代码:
1
2
3
4
5
6
7
8 %% 计算f'(x)
syms x
f=(exp(x^2))/(x^3-x+3);
diff(f)
%% 计算g'(x)
syms x y
g=(x^2+x*y-1)/(y^3+x+3);
diff(g,'x') % 指出求导对象
1
2
3
4 %% 计算定积分 此处利用牛顿-莱布尼兹公式
syms x
y=int((x^2-x+1)/(x+3));
subs(y,x,10)-subs(y,x,0)积分结果为:
方程式数值解
在数值分析那门课程中, 介绍了求解方程的数值解的一些方法, 数值分析是一门很难的课程, 以后有机会可能会尝试学习一下.
在中学的学习中, 我们所接触的方程 包括一元方程组, 一元二次方程等等都可以导出其求根公式, 也就是说那些方程的根与其未知数的系数有关系, 通过后来的学习, 也认识到一元三次方程也存在公式解. 那么, 对于一元四次方程, 五次方程等等高次方程有没有公式解呢? 经过复杂的证明, 5次方程以上的方程没有公式解! 对于第一次听到这个消息的小伙伴可能也会像我一样有些理解不了, 方程式的根竟然不能用系数来表示? 但是事实就是这样. 因此, 研究方程的数值解法就显得很有必要.
方程式求根的数值解法常见的有:
- 二分法
- 牛顿法
二分法思想比较简单, 不做过多介绍. 这里直接给出算法流程图.
下面介绍一下牛顿法的逼近过程是怎样的.
牛顿法首先需要从某一点出发, 计算以及在点处的切线.
记此切线与x轴相交于点, 计算以及在点处的切线,
记此切线与x轴相交于点, . . . .
随着迭代次数的增加, 的数值会逐渐减小 , 当小于精度时, 即可停止迭代.其算法示意图如下:
算法流程图:
下表中给出二分法与牛顿法的主要区别:
matlab中求方程的数值解通常使用fzero()
或者fsolve()
, 这两个函数的传入参数都是函数句柄
fzero()
函数相当于使用二分法求解, 因此函数必须穿过x轴, 对于这样的函数, fzero()
无法求解, 因为区间端点的函数值的乘积大于0.
fsolve()
相当于使用牛顿法求解, 因此除了要给出求解函数之外, 还需要给出迭代的初始点. 下面分别举例做介绍.
求 的零点
1 | f2 = @(x) (1.2*x+0.3+x*sin(x)); |
运行结果:
这两个函数还有一些可选参数.
1 | f=@(x)x.^2 |
运行结果:
对于多项式, 可以使用roots
函数来求方程式的数值解, 例如:
求解
1 | roots([1 -3.5 2.75 2.125 -3.875 1.25]) |
运行结果:
练习:
求方程组的根, 使用初始迭代点为
参考代码:
1
2
3
4 F = @(x) [2*x(1) - x(2) - exp(-x(1));
-x(1) + 2*x(2) - exp(-x(2))];
x0 = [-5;-5];
[x,fval] = fsolve(F,x0)运行结果:
下面比较一下数值计算与解析计算的各自的优势与缺点.
上面介绍的数值计算的方法都是基于迭代的, 还有一类问题处理方式与上面的方法恰恰相反, 那就是递归问题. 递归函数就是指在函数体内又调用了函数本身.
比如求解时 , 就可以采用递归算法进行求解.
1 | function output = fact(n) |