1.2 符号变量
MATLAB定义符号变量有两个函数sym() 和syms()。比如下例,用sym() 创建x和y两个符号变量,相应代码如下:
x = sym('x'); y = sym('y');
syms() 也可以创建这两个符号变量:
syms x y
另外,符号变量可以创建表达式。比如下例,首先创建a、b、c和x这四个符号变量,然后用它们构造一个一元二次多项式,并赋值给f。latex() 函数将f变成Latex字符串。symvar() 在表达式中查找符号变量。旧版MATLAB曾采用findsym()函数来查找符号变量,新版已经停止更新支持。
syms a b c x f = a*x^2 + b*x + c latex(f) % converted to a Latex string % 'a\,x^2+b\,x+c' symvar(f) % [ a, b, c, x]
除了简单多项式,符号变量还能构造复杂符号多项式。比如下例,先构建了符号变量t,后定义f1和f2两个三角函数,并且用expand() 展开。
syms t f1 = sin(2*t) expand(f1) % 2*cos(t)*sin(t) f2 = cos(2*t) expand(f2) % 2*cos(t)^2 – 1
sym()和syms()函数在定义符号变量时,还可以设置这些变量的假定条件,比如下例:
x = sym('x','real'); y = sym('y','positive'); z = sym('z','rational'); assumptions % [ in(x, 'real'), in(z, 'rational'), 0 < y] syms x y integer syms z rational assumptions % ans = % [ in(x, 'integer'), in(y, 'integer'), in(z, 'rational')]
另外,MATLAB有专门函数assume() 设置符号变量假定条件,assumeAlso() 追加假设条件,assumptions() 函数返回这些条件,比如下例:
%% multiple assumptions syms x assume(x > 5) assumeAlso(x < 10) % assume(x>5 & x<10) assumeAlso(x,'integer') assumptions % [ in(x, 'integer'), 5 < x, x < 10]
通过如下代码给x设置若干假设。
assume(in(x,'integer') & x>2 & x<10)
配合solve() 函数,下例测试假设条件。
syms x assume(x/2,'integer') solve(x>0,x<10,x) % ans = % % 2 % 4 % 6 % 8 assume((x-1)/2,'integer') solve(x>0,x<10,x) % ans = % % 1 % 3 % 5 % 7 % 9
如下代码清除有关x的所有假设条件。
assume(x,'clear')
表1.4给出了利用assume() 函数设定符号变量假定条件的一些例子。
表1.4 用assume() 给符号变量假设条件
另外,whos() 函数把workspace当前变量列出来,比如下例:
clc; clear all; syms a x b = 2; c = 1; f = a*x^2 + b*x + c latex(f) % converted to a Latex string % 'a\,x^2+b\,x+c' symvar(f) % [ a, b, c, x] whos
运行代码,函数whos() 得到结果如下:
ans 1x2 8 sym b 1x1 8 double c 1x1 8 double f 1x1 8 sym x 1x1 8 sym
与普通运算相比较,MATLAB符号运算一般较慢。请大家比较下列加法运算时间:
a = 1/2; b = 1/3; c = sym(a); d = sym(b); tic a + b toc tic c + d toc
新版MATLAB sym()函数不再支持表达式输入,比如f1 = sym('x + 1')在新版MATLAB不合法。解决这个问题有如下几种方式。第一种方法是先用syms定义符号变量x,然后再定义函数,即:
syms x f1 = x + 1
或者:
syms f1(x) f1(x) = x + 1;
再或者:
f1 = sym('x') + 1;
加、减、乘、右除(forward slash, /)、左除(backward slash, \)和乘幂均可用在符号表达式上。
f1 + f2 % x^3 + 2*x^2 + 2*x + 2 f1 - f2 % x^3 f1*f2 % (x^2 + x + 1)*(x^3 + x^2 + x + 1) f1/f2 % (x^3 + x^2 + x + 1)/(x^2 + x + 1) f1\f2 % (x^2 + x + 1)/(x^3 + x^2 + x + 1) f1^2 % (x^3 + x^2 + x + 1)^2
MATLAB函数numden() 提取符号数值和表达式中的分子(numerator)和分母(denominator),比如下面三个例子:
[n, d] = numden(sym(4/5)) % n = 4 % d = 5 syms x y [n,d] = numden(x/y + y/x) % n = x^2 + y^2 % d = x*y f = (x^2 + 1)/(x + 1) + x/(x - 1); [n,d] = numden(f) % n = x^3 + 2*x - 1 % d = (x - 1)*(x + 1)
compose() 函数构造复合函数。例如下面两个函数:
如下代码定义上式:
syms x y t f = 1/(x + 1); g = sin(y);
compose(f, g)将返回复合函数f(g(⋅))。
如下代码构造上式。
f1 = compose(f,g) % returns f(g(y)) where f = f(x) and g = g(y) % f1 = 1/(sin(y) + 1)
compose(f, g, t)则返回复合函数f(g(t))。
如下代码构造上式。
f2 = compose(f,g,t) % returns f(g(z)) % f2 = 1/(sin(t) + 1)
compose()函数的更多用法请参考链接:
https://www.mathworks.com/help/symbolic/compose.html
函数finverse()用来求解反函数,比如下例:
syms x f(x) = 1/tan(x); g = finverse(f) % g(x) = atan(1/x)
本丛书经常用matlabFunction() 把符号表达转换成函数句柄,比如函数:
下例用matlabFunction() 将符号表达式转换为函数句柄cone() 和quadratic()。
syms a b c x y f1 = sqrt(x^2 + y^2); cone = matlabFunction(f1) % @(x,y)sqrt(x.^2+y.^2) cone(1,1) f2 = a*x^2 + b*x + c quadratic = matlabFunction(f2) % f2 = @(a,b,c,x)c+b.*x+a.*x.^2 % anonymous function quadratic(1,1,1,1) % 3 quadratic(1,1,1,sym('x')) % x^2 + x + 1
更多有关matlabFunction() 函数的用法,请参考链接:
https://ww2.mathworks.cn/help/symbolic/matlabfunction.html
MATLAB提供solve() 求解符号方程解。请读者注意,新版本的solve() 已经不再支持字符向量或字符串输入,比如solve('x^2 -1')或solve('x^2 -1 = 0')或solve('x^2 -1 = 0', 'x')均不合法。
比如求解如下一元二次方程:
可这样使用solve()函数:
syms x eqn = x^2 + x - 2 == 0 S = solve(eqn)
结果如下:
S = -2 1
又如,求解符号一元二次方程:
以下代码求解该一元二次等式:
syms a b c x eqn = a*x^2 + b*x + c == 0 S = solve(eqn)
结果如下:
S = -(b + (b^2 - 4*a*c)^(1/2))/(2*a) -(b - (b^2 - 4*a*c)^(1/2))/(2*a)
请读者注意,solve() 默认以x为未知量。而solve(eqn, a)则会以a为未知量,比如下例:
syms a b c x eqn = a*x^2 + b*x + c == 0 S = solve(eqn, a)
结果如下:
S = -(c + b*x)/x^2
solve()函数还可以用于求解方程组,比如如下二元一次方程组:
求解代码如下:
syms x y eqns = [x + y == 1, 2*x - y == 5]; vars = [x, y]; [sol_x, sol_y] = solve(eqns,vars)
结果如下:
sol_x = 2 sol_y = -1
solve() 函数也可以这样用:
S = solve(eqns,vars) S.x S.y
solve()函数的更多用法,请参考链接:
https://ww2.mathworks.cn/help/symbolic/solve.html
本丛书中经常使用MATLAB函数subs(),它将符号或数值代入符号表达式,如以下几个例子:
syms x y a b subs(x + y, a) % ans = % a + y subs(x + y, x, a) % ans = % a + y subs(x + y, y, a) % ans = % a + x subs(a + b, a, 4) % ans = % b + 4 subs(a*b^2, a*b, 5) % ans = % 5*b