19-03-06更新:现在我又觉得Python(Numpy+Pandas)最好用了 >_< 建议大家坚持初心就好,适合自己的才是最好的。我是CS学生,需要经常用脚本语言处理数据,这个时候,我最需要的就是能将矩阵处理与脚本语言结合的工具,那么当然是Python啦~
18-06-10更新:最近在用Mathematica,发现在矩阵处理以外的领域其功能远超MATLAB,推荐给各位
【原文】
本文旨在总结我在刚结束的MCM/ICM比赛中习得的MATLAB知识。总结的顺序力求由浅到深,以便日后复习。
MATLAB的下标从1开始
一、 基础:矩阵创建篇
这一章的标题用的不是“定义”,而是“创建”。这是因为这一章讲的不是严格的矩阵定义语法,而是在宽泛的应用中能够应用的矩阵创建方法。
MATLAB中,矩阵创建的方法有很多种。我在这里介绍常见的几种。
1 仅指定大小的zeros指令
用到的指令是zeros(n)
和zeros(sz1, ..., szN)
zeros(n)
创建一个n*n的零矩阵。
>> zeros(5)
ans =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
若要指定矩阵的维度和大小,可以用zeros(sz1, ..., szN)
创建任意确定大小和维度零矩阵。
>> zeros(1, 5)
ans =
0 0 0 0 0
>> zeros(5, 1)
ans =
0
0
0
0
0
>> zeros(2, 3, 4)
ans(:,:,1) =
0 0 0
0 0 0
ans(:,:,2) =
0 0 0
0 0 0
ans(:,:,3) =
0 0 0
0 0 0
ans(:,:,4) =
0 0 0
0 0 0
>>
有很多类似
zeros
的指令,可以指定矩阵的维度和大小,还可以对矩阵内的元素赋值。有使用需要时可以自行查找。(如ones
,eye
等)
2 指定开始 步长 结束 来创建一个向量
语法为
start : step : end
>> 1:1:10
ans =
1 2 3 4 5 6 7 8 9 10
>> 1:3:10
ans =
1 4 7 10
这个指令常见于for-end
循环,也可以用来快速创建向量。
3 指定值和大小的枚举式定义
这种创建的方法在很多教程中被列为第一种方法,但是我个人并不喜欢这种枚举的定义表达式。
这种创建方法常用于创建维度为2的矩阵。使用时仅需要记住,
分隔元素,;
分隔行。逗号可以用空格代替。
逗号分隔元素,分号分隔行。
>> [1, 2, 3; 4, 5, 6]
ans =
1 2 3
4 5 6
>> [1, 2, 3; 4, 5] %出错,不同行的长度必须一致
串联的矩阵的维度不一致。
>> [1 2 3; 4 5 6] %逗号可以用空格代替
ans =
1 2 3
4 5 6
>> [1, 2, 3, 4, 5]
ans =
1 2 3 4 5
>> [1; 2; 3; 4; 5]
ans =
1
2
3
4
5
4 不指定值和大小的定义
这个方法的语句很简单。
a = [];
这样定义的矩阵在使用时是直接对特定位置的元素赋值,因此有必要简单了解矩阵索引的形式。
MATLAB的矩阵索引是括号表达式,不同维度间用逗号分隔。如
a(3, 2)
。当二维矩阵的某一维长度为1时,可以仅用一个数字作为索引。如a(4)
。
知道了矩阵索引后,我们可以直接对想要赋值的位置赋值。这时该矩阵的行为非常重要。
- 如果目前的矩阵包含了指定的位置,直接赋值
- 如果目前的矩阵不够大,以至于指定的元素在矩阵之外。这时矩阵会扩大直至包括了指定的位置。扩大的部分全部赋值为0,指定的位置按指定值赋值。
>> a = [];
>> a (3, 4) = 5
a =
0 0 0 0
0 0 0 0
0 0 0 5
>> a = [];
>> a (5) = 6
a =
0 0 0 0 6
5 矩阵分割,获取大矩阵的一部分
MATLAB支持矩阵分割操作,但和python
的分割不完全相同。主要体现在:
的使用上。
二维矩阵分割语法:
b = a(m1 : m2, n1 : n2);
如果某一维不分割,即保留整行或整列时,这一维的分割可以直接写为:
,不用加数字。但是,只要不是整行或整列,冒号前后的数字都要写,不能省略。(和python
的区别)
>> a = [1, 2, 3; 4, 5, 6; 7, 8, 9]
a =
1 2 3
4 5 6
7 8 9
>> b = a(1:2, 1:2)
b =
1 2
4 5
>> b = a(:, 1:2)
b =
1 2
4 5
7 8
>> b = a(:2, 1:2) %出错,此时冒号前后的数字都不能省略
b = a(:2, 1:2)
↑
错误: 不应为 MATLAB 表达式。
经检验,用上述指令分割的矩阵独立,即程序为新的矩阵单独开辟了存储空间。
二、MATLAB基本指令一览
MATLAB只使用单引号。
1 控制台输入输出 input, disp, 和 fprintf
num = input ('请输入数字:');
disp(num);
input
指令的括号中是提示语句,执行时会在控制台显示。
disp
括号中是显示的元素,一般任何变量都能用disp
显示,不过只能显示一个变量。
重点讲fprintf
。这个指令非常类似c++
的printf
,第一个参数是控制串,用%d %f %s
等控制格式,后面跟着的参数是控制符对应的变量。
>> a1 = 3;
>> a2 = 5.4;
>> a3 = 'matlab good';
>> fprintf('%d is not %f, but %s', a1, a2, a3);
3 is not 5.400000, but matlab good>>
%在控制台键入该指令时会询问输出到哪个文件里
2 文件输入输出
3 图片输入输出
saveas (gcf, <filename>);
gcf
是一个保留字,作为saveas的第一个参数。
filename
的位置上填路径和文件名,Windows操作系统中路径由\
连接而成,注意文件名包含了后缀,即指定了目标格式。
常用的文件名可以有*.pic
。
4 判断语句 if-elseif-else-end 和 switch-case-end
if
判断的语法
if 条件1
语句块1
elseif 条件2
语句块2
elseif ...
...
elseif 条件n-1
语句块n-1
else
语句块n
end
switch
判断的语法
switch-case-end语法1 单值匹配
switch (switch_expr)
case case_expr_1,
statement_1
case case_expr_2,
statement_2
...
otherwise,
statement_other
end
swtich-case-end语法2 多值匹配
switch(switch_expr)
case {case_1, case_2, case_3},
statement_1
case {case_4, ...},
...
otherwise,
statement_other
end
5 循环语句 for-end 和while-end
for-end
循环的基本语法是
for <var> = <vector>
循环体
end
<var>
是控制变量,在for-end
循环中不停地从<vector>
向量中获取下一个元素。
因此,for-end
循环每循环一次,向量<vector>
中的下一个元素就被赋值给控制变量<var>
。知道<vector>
中元素耗尽,循环结束。
while-end
循环的基本语法是
while 条件
循环体
end
只要条件为真,就会执行一遍循环体。
可以用continue
和break
指令控制循环。
6 绘图指令 plot 及图像调整指令 legend 等
plot
指令用来绘制折线图,语法如下。
plot ( <x>, <y>, <shape> );
<x>
向量和<y>
向量对应一系列点的横纵坐标,<shape>
参数用来指定折线的形状。常见的有*-
, x-
, o-
, r:x
等。
画出来的图会直接显示出来,如果想要将多条曲线画在一幅图上,只需要在plot
后执行
hold on;
下面的指令可以设定图像的一些信息。
xlabel ( <xlabelname> ); %指定横坐标的名字
ylabel ( <ylabelname> ); %指定纵坐标的名字
legend ( <name1>, <name2>, ..., <nameN> ); %依次指定各曲线的图例文本
7 拟合工具 cftool 和 lsqcurvefit
直接在控制台执行cftool
即可显示cftool的界面,左上选定每一维的向量,右上设定拟合方式,左下显示拟合结果,右下图示拟合结果。
>> cftool;
lsqcurvefit
用于多元非线性拟合。详细讲来很复杂,我直接贴上代码。
function multifit (pp, gdp, prd, prc, cons)
%多元拟合函数,参数是很多向量
x = [pp; gdp; prd; prc]; %创建x矩阵
y = cons; %指定y轴变量
opt = optimset('MaxFunEvals',50000, 'MaxIter', 10000, 'TolFun', 1E-10);
%指定lsqcurvefit的一些选项
%MaxFunEvals 设定最大拟合次数
%MaxIter
%TolFun
b0 = [1, 1, 1, 1, 10];
%制定初始参数,这个变量有时会影响拟合结果,注意最后一个是常数项
b = lsqcurvefit (@myfun, b0, x, y, [], [], opt);
%拟合,myfun函数见下,拟合的结果参数存在变量b中
disp (b);
plot (y, 'o-'); %画出y,此时横坐标从1开始,直到size(y)
hold on; %在这副图中再叠加一条曲线
plot (myfun(b, x), 'r:x'); %画出拟合的曲线(折线)
saveas(gcf, 'data\part1_b_fit\tx_petro.fig') %保存图片
end
function y = myfun (x, xdata)
%myfun是指定的拟合函数原型,这里是一个对数线性函数原型
%参数x表示函数原型中的参数
%参数xdata中包含了所有变量的所有取值
A = x(1);
B = x(2);
C = x(3);
D = x(4);
E = x(5); %常数项
pp = xdata (1, :);
gdp = xdata (2, :);
prd = xdata (3, :);
prc = xdata (4, :);
y = exp(A*log(pp+1) + B*log(gdp+1) + C*log (prd+1) + D*log(prc+1) + E);
end
三、其他函数
size
一个参数时返回一个矩阵,表示参数变量的尺寸。
可选第二个参数n,指定返回第n维的尺寸。
figure
保留原图像,创建一张新的图像。
strcmp
比较字符串内容,相同返回真,不同返回假。常用在条件语句中。
cell
创建一个元胞(cell)矩阵。参数为矩阵的行数和列数。
数值操作
这一部分介绍4个指令:floor
,ceil
,round
,fix
-
floor
是下取整 -
ceil
是上取整 -
round
是绝对值四舍五入取整 -
fix
是向0取整
floor(1.6) %=1
ceil(1.6) %=2
round(1.6) %=2
fix(1.6) %=1
floor(-3.5) %=-4
ceil(-3.5) %=-3
round(-3.5) %=-4
fix(-3.5) %=-3
网友评论