MATLAB金融风险管理师FRM(高阶实战)
上QQ阅读APP看书,第一时间看更新

1.2 符号变量

MATLAB定义符号变量有两个函数sym() 和syms()。比如下例,用sym() 创建xy两个符号变量,相应代码如下:

x = sym('x');
y = sym('y');

syms() 也可以创建这两个符号变量:

syms x y

另外,符号变量可以创建表达式。比如下例,首先创建abcx这四个符号变量,然后用它们构造一个一元二次多项式,并赋值给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,后定义f1f2两个三角函数,并且用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)将返回复合函数fg(⋅))。

如下代码构造上式。

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)则返回复合函数fgt))。

如下代码构造上式。

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