数组及其运算、数据流式控制、数据读写

数组及其运算

数组是MATLAB运算的核心.

数组的创建, 类似于Python, 可以采用类似range和list的方法, 同时也有一些常用的数组可以直接用函数创建:

1:2:11     % 步始:步长:步终, 包括步始和步终
11:-2:1    % 步始、步终交换, 步长为负
1:11       % 直接使用步始、步终


linspace(1, 5, 3)     % 以等差构造, 首项1, 末项5, 3项
logspace(1, 5, 3)     % 以10^x构造, 首项10^1, 末项10^5, 3项


[1, 2, 3; 4, 5, 6]        % 2x3数组
a = [1; 3]; b = [2; 4];
[a, b]                    % 数组拼接


rng(1)                % 随机数种子
rand(2, 3)            % 0-1均匀分布, 2x3
randn(2)              % 标准正态分布, 2x2(只写一个为方阵)
randi([1, 10], 2, 3)  % 在1:10随机取整数, 2x3


ones(3)           % 全1矩阵
zeros(3)          % 全0矩阵
eye(3)            % 主对角为1其余为0
v = [1, 2, 3];
diag(v)           % 对角阵

MATLAB用小括号获取元素或者给该位置赋值, 小括号第几个数为第几个维度上的索引. 可以用数组索引, 类似于切片, 其中末下标保留字为 end.

MATLAB支持数组给数组赋值, 切片得到的数组同理, 因此可以赋值 [] 来消去一部分的数组. 如果用单一数字为下标, 进行迭代索引, 迭代顺序类似于:

伪代码:
for k:
    for j:
        for i:
            (i, j, k)

特殊的切片:

a = reshape(1:24, 4, 6);
a(:)
b = reshape(a, 2, 3, 4);
b(:, :)
% 利用:作为缺省时, 如果维度缺少一个, 则按照最后一个维度逐索引切片并沿倒数第二个维度拼接以实现维度压缩


b(:, 1, :)
% 给定有某一维度的索引, 则对所有该维度索引为给定索引的元素迭代, 新数组除该维度长度为索引长度外其余维度长度不变

MATLAB可以制造示性数组和条件索引数组:

(a > 0)       % 按照a > 0条件生成a的示性数组
find(a > 0)   % 满足条件的索引的数组
find(a)       % 按照惯例, 默认为非零即真

MATLAB支持数组给数组赋值, 切片得到的数组同理, 因此可以赋值[]来消去一部分的数组.

  • repmat(mat, [m, n]) 将一个数组 mat 按照 [m, n] 自拼接在一起.
  • reshape(mat, ...) 按照给定的形状将数组 mat 的元素迭代生成新数组.
  • flip(mat, axis) 得到一个新数组, 所有原本排列在 axis 轴方向上的元素倒序排列. flipud(mat) 等价于 flip(mat, 1), fliplr(mat) 等价于 flip(mat, 2).
  • rot90(mat, n) 将数组 mat 旋转 n 个90度; 还有 rot45rotxrotyrotz 等函数, 不论.

sort 用于排序:

a = reshape(1:12, 3, 4);
[~, idx] = sort(a)                    % 平行于轴1升序(默认), 可以解包赋值分别得到排序后数组和排序索引数组, 这里用~忽略了排序后数组
sort(a, 2, 'descend')                 % 平行于轴2排序, 'ascend'为升序, 'descend'为降序
sort(a, 'ComparisonMethod', 'abs')    % 取函数值排序

数组可以运算, 分为数组整体运算和逐元素运算:

a'    % 取共轭的转置
a*b   % 矩阵乘法
3*a   % 数乘3
a/b   % 相当于a*b逆
b\a   % 相当于b逆*a, 左除性能优于右除
a/3   % 数乘1/3
3\a   % 同上
a^4   % a的4次方
4^a   % 4的a次方


a.'   % 直接转置
a.*b  % a与b元素分别相乘
a./b  % a与b元素分别相除
b.\a  % 同上
4.^a  % 4的a各元素次方构成的数组
a.^4  % a各元素的4次方构成的数组

MATLAB的数据类型包括 double, uint8uint16booleancharstr. 前3种的转换函数分别为 double()uint8()uint16().

  • char(x) 是一个ASCII值为 x 的字符. str视为 char 行向量.
  • double(x) 等函数可以将字符转为ASCII值.

一套完整的转换流程:

a = 'Hello world!';
rowcode_a = double(a);                        % 转为ASCII值行向量
binstr_a = dec2bin(rowcode_a);                % 转为二进制码字符串的列向量
bin01_a = double(binstr_a) - double('0');     % 二进制码的字符串拆成01数字
colcode_a = bin01_a * (2.^(6:-1:0))';         % 一个常用转化, 重新得到ASCII值列向量
char(colcode_a')

常量保留字:

  • eps: 浮点数相对精度
  • ij: 复数单位
  • infInf: 无穷大
  • intmax: 最大正整数; intmin: 最小负整数
  • NaNnan: 非数, 用 isnan(x) 检测
  • pi: $\pi$
  • realmax: 最大正实数; realmin: 最小正实数

对于复数, 我们可以用 real(x)imag(x)x 的实、虚部, 用 abs(x)angle(x)x 的模长和辐角, 用 conj(x)x 的共轭.

进制分为 binoctdechex, 用 bin2dec(x) 一类的函数转化.

sumcumsumprodcumprod 求和与积:

sum(a)                % 将平行于轴1(默认)的子数组替换为它的和
sum(a, 2)             % 将平行于轴2的子数组替换为它的和
sum(a, 'all')         % 全部求和


cumsum(a)             % 将平行于轴1(默认)的子数组替换为累积和
cumsum(a, 2)          % 将平行于轴2的子数组替换为累积和
cumsum(a, 'reverse')  % 'reverse'为反向迭代


% prod、cumprod同上

maxmin 用于求最大最小值:

[b, idx1] = max(a)                % b为a平行于轴1(默认)的子数组替换为它的最大值得到的数组, idx1为各最大值在子数组中的索引的数组
max(a, [], 2)                     % 平行于轴2
max(a, [], 'all')                 % 全数组最大值
max(a, [], [2, 3])                % 平行于轴2-3平面的子数组替换为它的最大值得到的数组
[~, idx2] = max(a, [], 'linear')  % idx2为各最大值在整个数组的迭代索引的数组
max(x, y)                         % 两个形状一样的数组在每个位置上比较并取最大值


% min同上

基础的运算符如 ~ (取反)、& (位与)、| (位或)、&& (与)、|| (或) 按下不论. xor(a, b) 为异或. all(a) 为全真. any(a) 为存在真. 同时, 与 isnan(x) 相似, 我们有 isempty(a) 判断是否为空.这个主要是检查条件是否存在满足的, 如:

idx = find(condition); isempty(idx)
% 也可以用any
any(condition)

数据流式控制

条件语句:

if expr1
    cmd1
elseif expr2
    cmd2
else
    cmd3
end

循环语句:

while expr
    cmd
end


for i = arr
    cmd
end

选择语句:

switch expr
case val1
    cmd1
case val2
    cmd2
...
otherwise
    cmd_default
end

异常捕获:

try
    cmd1
catch ME  % 捕获为ME
    cmd2
end

数据读写

读写文件使用 saveload:

save file1.mat;                   % 把工作区写入file1.mat
save file2.mat a b;               % 把变量a和b写入file2.mat
save file2.mat c -append;         % 把变量c追加写入file2.mat
save file3.dat d -ascii;          % 把数组d以8位ascii写入file3.dat
save file4.dat e -ascii -double;  % 把数组e以16位ascii写入file4.dat


load file1.mat;                   % 读取file1.mat
load file2.mat a c;               % 读取file2.mat的变量a和c
load file3.dat -ascii;            % 读取8位ascii文件file3.dat, 创建数组file3并装入
load file4.dat -ascii;            % 读取16位ascii文件file4.dat, 创建数组file4并装入

类似于Python的 print(), MATLAB有 disp(). 可以用 format longformat short 一类的语句控制输出格式.


零星补充:

qr(a)     % QR分解
svd(a)    % SVD分解(奇异值分解)