字符与字符串、元胞、结构体、函数、符号运算、数据处理

字符与字符串

字符数组用单引号, 字符串用双引号.

strlength 可以求出字符串的长度.

通过 char 可以将字符串转化为字符数组; 相应的, 可以用 string 将字符数组转化为字符串.

字符串在数组中的地位与字符数组地位不同, 字符数组为多个值, 字符串为一个值, 可以看作是叠在二维上但保持数组本身维度不变的字符数组整体.

字符串占据了第二维, 因此字符串行向量是排在第三维上的:

% 2x3 -> 2x2x3
>> char(["s1", "s2", "s3"; "s4", "s5", "s6"])
(:, :, 1) = ['s1'; 's4']
(:, :, 2) = ['s2'; 's5']
(:, :, 3) = ['s3'; 's6']


% 2x3 -> 2x1
>> string(['1', '2', '3'; '4', '5', '6'])
["123"; "456"]

字符串作为一个整体值, 无法像字符数组一样支持ASCII值运算如减法、加法之类的.

字符串的加法为连接字符串.

字符数组与字符串可以和数字相互转化.

当使用 double 进行转化时, 字符数组是将ASCII值转化为 double 类型; 而字符串则会“忠实地”将字面值数字 (包括中间带一个空格、逗号或单撇的数字) 转化出来.

str2doublestr2num 可以对字符数组和字符串作用, 按字符字面提取数字:

>> double(['123'; '1e2'])
[49, 50, 51; 49, 101, 50]
>> double(["123"; "1e2"])
[123.0000; 100.0000]
>> double(["123", "456"])
[123, 456]
>> double(["123 456", "123,456", "123'456"])
[123456, 123456, 123456]


>> str2double(['123', '1e5'])
123100000
>> str2double(['123'; '456'])                     % 对于非向量字符数组, 按照迭代顺序提取
142536
>> str2double(['123'; '4e6'])                     % 同上
1.4200e+38
>> str2double(["123", "456"])
[123, 456]
>> str2double(["123,456"; "123 456"; "123'456"])  % 只有逗号分割被允许
[123456; NaN; NaN]


% str2num类似于Python里的eval
>> str2num('123; 456')
[123; 456]
>> str2num("123; 456")
[123; 456]

string 可以直接将数字转为一个字符串; 而想要变成字符数组, 需要使用 num2str.

>> num2str([123, 456])
'123  456'

字符数组可以索引, 字符串为整体值, 没有内部索引.

元胞

元胞类似于表格, 可以自动扩充.

当我们用小括号索引 (也就是通常的索引时), 我们总是得到一个元胞; 而当我们使用大括号索引时, 我们才能取到元胞中的值.

与数组不同, 元胞允许空值的存在, 我们没有赋值的地方默认为 [].

对一个元胞赋值为 [] 时可以清除这个元胞; 但是对元胞内容赋值为 [] 只能清除内容.

>> a = {1, 2, 3};
>> a{2, 2} = 'a'
{1, 2, 3;
[], 'a', []}
>> a(3, 3) = {1>0}
{1, 2, 3;
[], 'a', [];
[], [], 1}
>> for i = 1:3
       a{i, i} = [];  % 对元胞内部赋空值
   end
>> a
{[], 2, 3;
[], [], [];
[], [], []}
>> for i = 1:3
       a(1, :) = [];  % 清除元胞
   end
>> a
0x3 cell

元胞在数组中具有主导地位, 可以自动吸纳非元胞数据, 除非外面还有一层元胞:

>> [{1, 2}, 3]
{1, 2, 3}

>> {{1, 2}, 3}

{1x2 cell, 3}

mat2cellcell2mat 使得我们可以进行类似分块矩阵的运算:

>> a = [1, 2, 3, 4;
       5, 6, 7, 8;
       9, 10, 11, 12];
>> mat2cell(a, [1, 2], [1, 3])
{1, [2, 3, 4];
[5, 9], [6, 7, 8; 10, 11, 12]}
>> cell2mat({[1, 2], 3; [4, 5], 6})
[1, 2, 3; 4, 5, 6]

结构体

结构体类似于数据库, 对于其中每一组数据 (用索引取得), 分为若干字段记录数据.

>> s1.a = 1; s1.b = 'q'
s1 =
a | b
1 | 'q'
>> s1(2).a = 2; s1(2).b = 'w'
s1 =
a | b
1 | 'q'
2 | 'w'


>> s2 = struct('a', {1, 2}, 'b', {'q'})
s2 =
a | b
1 | 'q'
2 | 'q'

>> s2 = struct('a', {{1, 2}}, 'b', {'q'})

s2 =
a | b
1x2 cell | 'q'

结构体一次读取多个数据时, 会逐个将其输出而不是放入一个数组或元胞, 因此如果需要转运这些数据, 需要外面包裹数组或元胞:

>> a = struct('a', {78, 'char'});
>> [a.a]
'Nchar'
>> {a.a}
{78, 'char'}

结构体实际上是一种数组, 可以像常规数组一样合并.

其中, 2x1结构体和1x2结构体是类似的, 但是合并时就会变成二维结构体数组:

>> s1.x = 1; s1.y = 1;
>> s2.x = 2; s2.y = 2;
>> s3.x = 3; s3.y = 3;
>> s4.x = 4; s4.y = 4;
>> s = [s1, s2; s3, s4]
2x2 struct
>> s(1, 1)
x | y
1 | 1

函数

输入 [x1, ...] 输出 [y1, ...] 的函数 func 定义为:

function [y1, ...] = func(x1, ...)
    cmd
end

MATLAB定义函数一般从文件下方开始往上定义, 对于函数文件, 主函数须放在开头, 并且与文件名同; 而脚本中的局部函数, 只能放在文件最末尾.

句柄, 负责将函数进行传递以实现复杂功能的数据类型. 通过 @ 即可得到函数的句柄, 包括匿名函数:

>> a = 1;
>> f = @(x, y) a*x.*y;
>> clear a;                   % 与Python不同, 定义匿名函数时, a的值已经被记录为常值了
>> f([1, 2, 3], [4, 5, 6])
[4, 10, 18]

符号运算

定义变量:

syms a b              % 定义变量
syms c [2, 3]         % 定义矩阵
syms 'd%d%d' [2, 3]   % 对元素命名格式化
syms e 2              % 定义方阵


工作区:
a: 1x1 sym
b: 1x1 sym
c: 1x1 sym
c1_1 c1_2 c1_3 c2_1 c2_2 c2_3: 1x1 sym
d: 1x1 sym
d11 d12 d13 d21 d22 d23: 1x1 sym
e: 1x1 sym
e1_1 e1_2 e2_2 e_2: 1x1 sym

定义函数:

syms f(x) g(y)


工作区:
f: 1x1 symfun
g: 1x1 symfun
x: 1x1 sym

也可以使用 sym 函数式定义, 这时, 我们可以直接定义一个矩阵而非像 syms 一样用元素挤占工作区:

>> a = sym('a', 2)
a =
a_1,1 a_1,2
a_2,1 a_2,2
>> b = sym('b_q%d_%d', 2)
b =
b_q1,1 b_q1,2
b_q2,1 b_q2,2
% 以上输出的下划线指后面为脚标

有了这些变量的定义, 我们可以像正常数值一样计算它们, 但是符号计算是精确的:

>> 1/sym(123456)
1/123456
>> sym(1/123456)
1195356666259043/147573952589676412928

对于符号函数, 我们可以直接像常规函数一样使用; 但是对于符号运算出来的式子, 应当使用 subs 来进行数值计算:

>> syms a b
>> c = a+b^2;
>> subs(c, [a, b], [1.5, 1])
5/2
>> subs(c, {a, b}, {[1.5, 1; 2.1, 2], [1, 1; 3.25, 4]})
[5/2, 2; 1013/80, 18]

数据处理

前面的 saveload 分别有自己的函数式.

除了这两个, 还有读取文本的 fileread、向文本写入表格的 writetable、读取表格的 readtable、读取图像的 imread 和写图像的 imwrite.

曲线拟合器

在APP中选择曲线拟合器, 选择数据和拟合模型后, 即可得到拟合结果.

其中, 线性拟合为选择基函数, 通过基函数的线性组合进行拟合.

直方图

使用 histogram(data) 绘制 data 的直方图.

可以指定为 histogram(data, n) 或者 histogram(data, arr) 来确定其直方图的分组数, 其中 n 直接指定分组数, arr 指定分割点 (左闭右开).

histogram(..., key, value) 可以指定图的相关属性:

histogram(data, 'Normalization', 'probability')   % 矩形高度表示频率
histogram(data, 'Normalization', 'pdf')           % 矩形面积表示频率
histogram(data, 'FaceColor', [0.9,0.5,0.2])       % 调整颜色

零星补充:

[a, b] = deal([1, 2])     % 用deal实现解包
a = 1  b = 2


integral(@(x) x.^2, 0, 1) % 数值积分
0.3333


syms f(x)
f(x) = x.^2;
diff(f, 2)                % f的二阶导
2


fourier(cos(x))           % Fourier变换
pi*(dirac(w-1)+dirac(w+1))


laplace(f)                % Laplace变换
2/s^3