MATLAB 是美国 MathWorks 公司出品的商业 数学软件 ,用于 数据分析 无线通信 深度学习 图像处理 计算机视觉 信号处理 、量化金融与风险管理、机器人, 控制系统 等领域。

MATLAB 是 matrix&laboratory 两个词的 组合 ,意为矩阵工厂(矩阵实验室),软件主要面对科学计算、可视化以及交互式程序设计的高科技计算环境。它将 数值分析 矩阵计算 、科学数据可视化以及非 线性 动态系统的 建模 和仿真等诸多强大功能集成在一个易于使用的视窗环境中,为科学研究、工程设计以及必须进行有效数值计算的众多科学领域提供了一种全面的解决方案,并在很大程度上摆脱了传统非交互式 程序设计语言 (如 C、Fortran)的编辑模式。

MATLAB 和 Mathematica Maple 并称为三大数学软件。它在数学类科技应用软件中在数值计算方面首屈一指。行 矩阵 运算、绘制函数和数据、实现算法、创建用户界面、连接其他编程语言的程序等。 MATLAB 的基本数据单位是矩阵,它的 指令 表达式 与数学、工程中常用的形式十分相似,故用 MATLAB 来解算问题要比用 C , FORTRAN 等语言完成相同的事情简捷得多,并且 MATLAB 也吸收了像 Maple 等软件的优点,使MATLAB成为一个强大的 数学软件 。在新的版本中也加入了对 C FORTRAN C++ JAVA 的支持。

help 命令查看帮助

help func;				% 帮助

可以从其它文件中载入数据

x = load('test.txt');

无论在脚本文件还是在函数文件中,都会定义一些变量。函数文件所定义的变量是局部变量,这些变量独立于其他函数的局部变量和工作空间的变量,即只能在该函数的工作空间引用,而不能在其他函数工作空间和命令工作空间引用。

但是如果某些变量被定义成全局变量,就可以在整个工作空间进行存取和修改,以实现共享。因此,定义全局变量是函数间传递信息的一种手段。

global A B C
save name 				 % 保存一个指定名称的命名空间(当前所有变量储存在其中)
save name var1 var2 ...   % 保存包含这些变量的命名空间
load name 				 % 载入一个指定名称的命名空间

用户可以自定义函数, matlab 函数通过值传递并能返回多个返回值,按如下格式定义函数:

function [输出1, 输出2, ...] = name(输入1, 输入2, ...)
	% code

例如我们可以定义计算 sin 的函数

function s = sind(x)
    % SIND(x) Calculates sine(x) in degrees
    s = sin(x*pi/180);

matlab 中也有内联(inline)函数,例如将如下方程组:

\[\left\{\begin{aligned} &\sin x_1 + x_2 + x_3^2e^{x_1} - 4 = 0\\ &x_1 + x_2x_3 = 0\\ &x_1x_2x_3 = -2 \end{aligned}\right. \]

转化为下面的形式函数:

f = @(x) [sin(x(1)) + x(2) + x(3)^2*exp(x(1))-4; ...
x(1) + x(2)*x(3); x(1)*x(2)*x(3)+2];

这样就可以直接通过 f(x) 来调用该函数,返回一个结果向量;相当于求解该函数等于 [0 0 0] 的解。

需要注意,函数应当定义在一个单独的文件中,然后在其它文件中直接使用即可。

syms x y z 		% 表示用 x y z 作为变量
u = x^2+y^2;	% 定义函数

函数取值 u(1,2,z) 得到一个 z 的函数

subs(u,x,y,1,2);

使用 disp 输出

disp(subs(u,x,y,1,2));

. 表示两个向量的元素一对一地进行运算,因此当需要计算向量元素依次运算时,可以利用 .*./.^ 算符对每个元素分别操作

a = [1 2 3];
b = [1 2 3];
a.*b => [1 4 9]
a.^b => [1 4 27]

加法、减法、乘法遵循矩阵的运算,但除法有所不同:

  • 左除 \ 表示将 A 的逆乘在左边 A\b
  • 右除 / 表示将 A 的逆乘在右边 A/b
  • 利用上引号 ' 来进行转置操作,例如

    A = [1 2 3]
    A' = [1 2 3]^T
    
    ind = find(X)
    

    找出矩阵 X 中的所有非零元素,并将这些元素的线性索引值(linear indices:按列)返回到向量 ind 中。如果 X 是一个行向量,则 ind 是一个行向量;否则,ind是一个列向量。

    ind = find(X, k)
    

    找到前 k 个不为 0 的线性索引值。 k 必须是一个正数,但是它可以是任何数字数值类型。

    ind = find(X, k, 'last')
    

    找到后 k 个不为零元素的线性索引值。

    返回矩阵 X 中非零元素的行和列的索引值。如果 X 是一个N(N>2)维矩阵,col 包括列的线性索引。

    [row,col] = find(X, ...)
    

    通过上述方式查找到的索引可以直接运用于矩阵切片

    X = [0 1 2 -1]
    ind = find(X < 1);
    A(ind, :);
    

    获取向量 X 中小于 1 的元素索引,然后取矩阵 A 中对应行的切片。

    我们也可以直接使用条件来进行切片而不必使用 find

    X = [0 1 2 -1]
    A(X < 1, :);
    

    最终得到的效果与上面相同。

    可以设置查找要满足的条件

    X = [1 2 ; 3 4 ];
    d = (X > 1) & (X < 4);
    

    这里 d 就是查找条件,它会返回一个 X 中满足条件的元素的下标矩阵。

    [row,col] = find(d);
    

    然后开启查找,会返回坐标向量,其中 row 和 col 分别记录满足条件的元素的行列坐标。

    当然也可以直接查找

    [row,col] = find(X > 1 & X < 4, 2);
    

    这里查找在 1 到 4 之间的前 2 个元素。

    需要注意, find 有精度要求,如果搜索精度过高会找不到,因此需要设定一个最小误差

    t = (abs(x - x0) < 1e-5 & abs(y - y0) < 1e-5 );
    

    maxk, mink, topkrows 都是在 R2017b 版本推出的新函数,用于求取矩阵的最大/最小的 k 个元素/行。

    B = maxk(A, k);
    B = maxk(A, k, dim);
    

    寻找 A 的 dim 维中前 k 个最大的元素。类似地

    B = mink(A, k);
    B = mink(A, k, dim);
    

    以及查找前 k 个最大的行

    B = topkrows(X, k);
    B = topkrows(X, k, dim);
    

    matlab 中直接可以定义字符串,并且可以用单/双引号表示字符串

    a = "hello"
    b = 'hello'
    

    下面是字符串相关函数

    求得结果可以在给定点取值。注意它不能取得数值,只能取得表达式,因此给定值的个数不能超过未知数的个数

    subs(diff(u,x),x,y,1,2); % 在 x = 1, y = 2 取值
    

    只带其中一个变量的值

    subs(diff(u,x),x,1);	% 在 x = 1 取值
    

    最后会得到有关 y 的函数或者可以直接得到函数的 Jacobi 矩阵:

    J = jacobian(u,[x y]);
    

    Matlab 没有内置直接计算数值求导的函数,只能把求导转化为差分格式。例如已知横坐标向量 x 和对应的函数值向量 y ,则导数向量可以被估计为

    diff(y)./diff(x);
    

    对于求梯度的时候, Matlab 有内置的函数,例如求 \(u=x^2y^3\) 在点 \((1,-2)\) 处的梯度

    x = -3:0.2:3;	  % 将函数在一个 x y 的二维矩阵中离散
    y = x'; 		 % 这里 y 做了转置
    f = x.^2 ∗ y.^3;				% 计算函数的二维矩阵
    [fx,fy] = gradient(f,0.2,0.2);	 % 求梯度
    % 要找到 x = 1, y = -2 的那个点
    x0 = 1;
    y0 = -2;
    % 判断表达式
    t = (x == x0) & (y == y0);
    % 寻找条件
    indt = find(t);
    % 查找满足坐标条件 x = 1, y = -2 的那个点的值
    grad = [fx(indt) fy(indt)];
    

    我们介绍其中的部分函数

    gradient(F, dx, dy, ...);
    

    它会求取矩阵 F 在不同方向上的梯度,默认每个方向的间隔为 1

    x = gradient(F);
    

    它会求出向量 F 的梯度向量 \(\partial F/\partial x\) ,默认间隔为 1

    [x y] = gradient(F, 0.2, 0.2);
    

    它会求出二维矩阵 F 的两个梯度向量 \(\partial F/\partial x\)\(\partial F/\partial y\) ,每个方向间隔为 0.2

    求解线性方程组

    设方程组形式为 \(Ax=b\) ,分为适定、超定、欠定三种情况讨论。

    适定方程组

    inv(A)*b;

    [L,U] = lu(A); x = U\(L\b);

    超定方程组

    A\b; 求得最小二乘解

    x = pinv(A)*b; 利用矩阵伪逆求解

    欠定方程组:

    A\b; 求得最小二乘解

    x = pinv(A)*b; 利用矩阵伪逆求解

    上面两种方法都只能求得一个特解,利用 null(A) 可以求得零空间,通过零空间的线性组合加特解可以得到通解

    通过向量 \(p=[a_0,a_1,\cdots,a_n]\) ,多项式降幂排列系数数组可以直接构造多项式

    poly2sym(p)
    

    这个函数在 symbolic 包当中,需要手动安装

    我们可以直接将数组当做一个多项式使用。通过将两个数组补充为相同长度,就可以通过数组加减进行多项式加减;还可以做乘法

    p = conv(p1, p2)
    

    返回相乘后得到的数组;以及带余除法

    [p, r] = deconv(p1, p2)
    

    返回商数组和余数数组;也可以进行积分和求导,同样返回结果数组

    de = polyder(p);
    in = polyint(p);
    

    可以对多项式逐点求值,也可以利用函数转换为向量或矩阵

    polyval(p, x)  			 % 单点求值
    polyval(p, [x y]) 		 % 数组求值,返回向量
    polyvalm(p, [x y; z w])   % 矩阵求值,返回矩阵
    

    通过 roots 函数求多项式的所有根

    roots(p)
    

    最后给出两个暂时不用的函数:

    polyeig	% 求解特征值问题
    residue % 部分分式展开
    

    多项式插值

    interp1(x, y, x1, 'method')
    

    其中 x y 表示节点和对应的值,x1 是要插值的点,最终会返回 y1 ,表示插值多项式在 x1 处的值向量;最后一个参数选择插值方法:

    method
    plot(x);			% x 的序号作为横坐标, x 值为纵坐标
    plot(x, y); 		% 其中x, y分别为横纵坐标数据
    subplot(a, b, c);    % 表示在一个格子中画图,分成axb的格子,在第c个格子里画图,其中格子的顺序为从左到右从上到下
    

    可以对颜色和样式进行选择

  • ro 代表红色圆圈
  • b 代表蓝色点
  • plot(re(:, 1), re(:, 2), '.', 'MarkerSize', 20);
    plot(re(:, 1), re(:, 2)./(re(:, 1).*log(re(:, 1))), '.');
    plot(x, x.^2);	% 绘制y = x^2的图像
    % 这表示将re分成re(:, 1)和re(:, 2)两个列向量
    

    注意:由于这是向量运算,如果报错的话,尽量在每一个运算前加点'.'

    plot 参数

  • 曲线线型、颜色和标记点类型
  • plot(X1,Y1,LineSpec,...) % 通过字符串LineSpec指定曲线的线型、颜色及数据点的标记类型
    % 注意:这些标识符写在一个字符串里
    plot(x, y, '-b');
    

    linspace(a, b) 设置区间为a到b

    x = linspace(-10, 10); % 设置 x 自变量为 -10 到 10
    plot(x, sin(x)); 	   % 绘制 sinx 在 -10 到 10 的图像
    

    绘制三维曲线的函数

    plot3(x, y, z);
    

    具体使用类似于 plot 函数;还可以绘制三维网格

    mesh(x, y, z);
    

    绘制三维曲面

    surf(x, y, z);
    

    使用 hist 函数绘制直方图,它有如下几种用法:

    hist(w);		% 绘制向量 w 的直方图
    

    此时,向量 w 的数据范围作为横坐标的区间范围,然后从左向右将出现在该区间中的元素个数(频数)作为纵坐标

    如图是一个 100000 维数组绘制的直方图,图中柱形的高度之和就是 100000 。

  • 划分区间个数
  • hist(w, n);
    

    可以指定将区间范围划分为 n 块,然后从左向右将出现在该区间中的元素个数(频数)作为纵坐标

    这是之前的 100000 维数组在 50 个区间上的频数直方图。