在 Coursera 上学习 MATLAB 课程的过程中,自己把笔记整理总结了一下,一方面方便自己日后的参考,另一方面也提供给大家一些资源和经验。
MATLAB 程序设计入门
【前言】这一部分偏重的是基于 MATLAB 的程序设计,即编程的方法,当然也包含了很多 MATLAB 的基础操作。个人觉得,之后对 MATLAB 一些工具的使用在有了 MATLAB 的编程基础的前提下回变得相对的轻松。
我是在 15 年下半年(大一)在 Coursera 学习了这一门课 MATLAB 程序设计入门,英文课程,总体难度不大,毕竟是针对初学者的课程。但有一些章节的课后作业还是挺有难度的。 下面是我在学习这一课程过程中的笔记,因为是在课余学习的,只记了关键的一些操作与命令。考虑会在后续补上截图与操作。
MATLAB 应用
后续不断补充
Mathworks 官方资源
矩阵的操作
克隆运算符(Colon Operator)
x=1:3:7
生成数组 1 4 7
表示 x 从 1 开始逐加 3,到 x<=7,相当于 for (i=1; i<=7; i+=3)
这样一个循环。
x=1:100
,生成 1 2 3...100
序列,即中间参数没有指定时默认逐加 1。
操作矩阵的一部分(Access Parts of a Matrix)
有如下的一些方法: 假设 x= 1 2 3 4 5 6 7 8 9
x(2,3)
矩阵 x 第 2 行,第 3 列的元素 6
x(end,2)
矩阵 x 最后一行,第 2 列的元素 8
x(2,[1 3])
矩阵 x 第 2 行的第 1 列和第 3 列的元素 4 6
x(2,1:3)
第二行的 1,2,3 列元素 4 5 6
x(:,2)
第 2 列所有元素
[m,n] = size(x)
得到 m 为行数,n 为列数
sum(x)
对逐列求和,输出每列和的行向量 12 15 18
矩阵生成(Matrix Building)
指定元素
zeros(5,6)
:5×6 的方阵,元素全为 0
ones(4,2)
:4×2 的方阵,元素全为 1
5*ones(4,2)
:元素全为 5
zeros(4)
:4×4 的方阵
diag(7 3 9 2)
:对角阵,7 3 9 2 位于其主对角线上,其余元素全为 0
随机元素
rand(3,4)
,rand(5)
:分别生成 3×4 和 5×5 的矩阵,元素值 0-1
fix(1+rand(5,4)*10)
:fix 为取整
randi(10,4,5)
:生成 1-10 的 4×5 矩阵
randi([5 10],4,5)
:生成 5-10 的 4×5 矩阵
randn(1,1000)
:n 代表 normal,按正态分布生成随机数
随机数生成器(Random Generator)
每次打开 MATLAB 后 rand 的值便固定了。需要重置随机数。
rng(参数)
,参数部分可以是数字,可以是字符串。
函数与脚本
函数 - Function
MATLAB 自带了丰富的函数,当然我们也可以自定义函数来实现自己想要的功能。
比如:rand(3,4)
就能生成 3×4 的数表,每个数在 0~1 之间。
输入 edit
编辑新文件
|
|
保存为 myRand.m
,这样就定义了一个 myRand 函数,用来生成 1-10 之间的数。其中 a 为局部变量,只在其作用域 (myRand) 中有效。
就这样执行 myRand
结果会被保存在变量 ans 中。
修改一下第一行:function a = myRand
,本意是想输出 a,运行之后会发现输出了 a=... ans=...
两个部分。想要只输出 ans,只需在 a=1+rand(3,4)*9
后加上 ;
输入 b=myRand
便可将值保存到变量 b 里。
将函数修改一下
|
|
就可以输出在low~high之间的随机数表了。若想输出a中的全部数字的和,则可以改成如下
|
|
然后在命令行中输入 [x ss]=myRand(1,10)
就会分别输出数表 x 及所有数字之和 ss
function 的定义
|
|
不确定函数名是否已定义,可以用 help exist
subfunction - 定义多个 (子) 函数
举个栗子
|
|
全局变量
|
|
一定要分开写 新手尽量少使用,可能会导致难检测的错误。
function 的优点
- 将一个大问题分解
- 功能的分解
- 代码复用
- 普遍性
Script - 脚本
是一个 .m
文件,用来执行一系列命令、赋值等计算
执行脚本时只需输名字
|
|
分支结构
if语句
function guess_my_number(x)
if x == 2
fprintf('Congrats! You guessed my number!\n');
end
注意每个 if 语句都要以 end 结尾
if-else语句
function guess_my_number(x)
if x == 2
fprintf('Congrats! You guessed my number!\n');
else
fprintf('Not right, but a good guess.\n');
end
if-elseif-else 语句
|
|
最后一个 else 可以不要,就是一个 if-elseif 结构。
关系运算符(Relational operators)
运算符 | 含义 |
---|---|
== | 判断是否等于 |
~= | 是否不等于 |
> | 是否大于 |
< | 是否小于 |
>= | 是否大于等于 |
<= | 是否小于等于 |
进行判断后返回值为 1 (真) 或 0 (假)
可以进行一组数的比较
|
|
当然也可以这样,逐个与 4 进行比较:
|
|
还有很多玩法
|
|
逻辑运算符(Logical operators)
运算符 | 含义 |
---|---|
&& | 逻辑与 |
|| | 逻辑或 |
~ | 逻辑非 |
输入 | && | || | |
---|---|---|---|
false | false | 0 | 0 |
false | true | 0 | 1 |
true | false | 0 | 1 |
true | true | 1 | 1 |
非零为真,零为假
|
|
但对两个矩阵使用 &&
和 ||
,应变为 &
和 |
|
|
help precedence
获取关于运算符优先级的帮助
循环嵌套(Nested if-statements)
|
|
多态函数
多态函数(Polymorphic functions)
什么是多态
是指函数可以根据输入输出的表达式 个数 和 类型 作出不同的反应。
举个栗子:zeros(5,6)
生成 5×6 矩阵,zeros(4)
生成 4×4 的矩阵。
MATLAB 中许多内置的函数是多态的(sqrt, max, size, plot, etc.)
如何使自己的函数具有多态性?
nargin: 返回实际的输入参数的个数 nargout: 返回实际要求的输出参数个数
下面这个函数 multable(n,m)
生成 n×m 的数阵,我们来使其具有多态性
|
|
[table s] = multable(3,4)
,会输出 3×4 的数表和其所有元素和
table = multable(5)
,只会输出 5×5 数表
健壮性(Robustness)
一个健壮的函数,会对各种可能出现错误的情况进行处理。上面的函数可以进行如下的优化:
|
|
%
后为注释,在命令行中输入 help multable
,可以得到最上面一大段注释作为 help 的内容
持续变量(Persistent variables)
和全局变量类似,但又有所区别。
|
|
也就是说,再次调用这个函数的时候,summa 的值是接着上次的值的。
重置:clear accumulate
输入输出和绘图
输入 & 输出(Input&Output)
|
|
上面实现了输入一个 x,并将 x+1 赋值给 a,input 括号中的为控制台输出的提示信息。
|
|
输出一行信息
|
|
fprintf 中的 f 代表 format,即格式化。
%d
,整数
%.2f
,f 代表 fixed point,小数位为 2 位
%5.2
,共 5 位(包括小数点),小数点后 2 位。
|
|
会输出
|
|
绘图(Plot)
|
|
绘图一般是先生成数列,再绘图
plot(t,b)
,以 t 为 x 轴,b 为 y 轴
figure(2)
,新建第 2 个空白的图像,如果有就切换到这个图像
|
|
自定义图像样式
plot(t,b,'m--o')
,最后一个参数中,m 表示 magenta (品红色),-- 表示虚线,o 表示小圆圈标出每个点。可以在 help plot
中找到更多相关参数
hold on
在当前 figure 上保留画出来的 图像,可以再做图像。与之相对的是 hold off
plot(x2,y2,'r:')
,红色连续点线,plot(x1,y1,'g*')
,绿色,点用 * 表示
grid
,打开网格
title('xxxx')
,加上标题
xlabel('xxxx')
,x 轴加上标签
ylabel('xxxx')
,y 轴加上标签
legend('sine','consine')
,图例说明
axis([-2 12 -1.5 1.5])
,指定 x 轴从 - 2 到 12,y 轴从 - 1.5 到 1.5
close(1)
,关闭 figure1
close all
,关闭所有图像
数据类型
数据类型(Datatypes)
同其他的编程语言一样,MATLAB 也有许多的数据类型。下面我们来看看我们用过哪些数据类型。
class(arg)
可以返回 arg 的类型。如:
|
|
whos
命令可以列出当前工作区域变量的详细信息。
数字类型(Numerical Types)
双精度实数(Double)
- MATLAB 中默认的数据类型
- 浮点表示形式,例如:12.34 = 1234 * 10-2
- 内存占用:64 bits(8 bytes)
单精度实数(Single)
- 与双精度类似。
- 内存占用:32 bits(4 bytes)
整数类型(Integer types
- 分为有符号(Signed)、无符号(Unsigned)两类
- 内存占用:8, 16, 32, 64 bit long
数据类型 | 范围 |
---|---|
int8 | -27~27-1 |
int16 | -215~215-1 |
int32 | -231~231-1 |
int64 | -263~263-1 |
uint8 | 0~28-1 |
uint16 | 0~216-1 |
uint32 | 0~232-1 |
uint64 | 0~264-1 |
single | -3.4×1038~3.4×1038 |
double | -1.79×10308~1.79×10308 |
一些实用的函数
类型检测
class
返回类型
isa
返回是否是这个类型,例如
|
|
范围检测
intmax
intmin
realmax
realmin
|
|
类型转换
|
|
需要说明的是,当一个变量重新赋值时,会转换为所赋值的类型。
字符串(Strings)
字符串,顾名思义,是由一串字符组成的。
在 MATLAB 中,字符串其实是一个向量,其中的元素自然是字符(char),字符又是由 ASCII 码值,可以得到一个打印所有可见字符的例子:
|
|
MATLAB 中,有一些常用的操作字符串的函数:
函数 | 作用 |
---|---|
findstr | 找到字符串中的子串 |
num2str | 将数字转换为字符串 |
str2num | 将字符串转换为数字 |
strcmp | 比较两个字符串 |
lower | 将字符串转换为小写 |
upper | 将字符串转换为大写 |
sprintf | 将结果写入字符串中 |
具体使用方法可以参考 MATLAB 自带的 WIKI
注:strcmp
在比较时严格区分大小写,若忽略大小写,可以用 strcmpi
sprintf
的用法和 fprintf
用法基本一致,但区别在于 sprintf
返回一个字符串
结构体类型(Structs)
众所周知,在 MATLAB 中,一个数列只能包含类型相同的一组数据,那我们需要存储类型不同的数据怎么办呢?结构体就能做到。
结构体和数组的区别:
- 结构体的基本单位是字段 (fields) 而非元素 (elements)
- 我们访问结构体时用的是字段名称 (field name) 而非索引 (indices)
- 字段可以有不同的数据类型 (甚至是另一个结构体)
灵活性:字段可以包含子结构体;结构体可以包含数组,同时数组元素也可以是结构体
下面来实践一下:
|
|
一些常用的操作结构体的函数:
函数 | 作用 |
---|---|
isfield | 判断结构体中是否有字段 |
setfield | 动态添加字段 |
rmfield | 删除结构体中的一个字段 |
struct | 快速构造一个结构体 |
结构体数组:在已经定义了一个结构体的前提下,可以快速构造结构体数组。已知 account
为一个结构体
|
|
值得注意的是,在 account(2)
中,除了赋过值的 number
字段外,其它字段初始为空
在一个结构体数组中,如果一个结构体的字段是一个子结构体,那么这两个子结构体不一定要相同。
注意:在使用 rmfield
时,应将返回值赋给要删除字段的结构体。
元胞数组(Cells)
这种类型也是 MATLAB 独有的,类似于 C 语言中的指针 (Pointer),但一个元胞 (Cell) 并不直接存内存的地址,而是指向某变量。
|
|
可以看出元胞数组的定义是用了一对花括号 {}
,而里面的数字类似于数组的索引。此外,你可以这样构建元胞数组:
|
|
类似于 2×3 的数组。但里面的每个元素都是元胞 (Cell)
注意:MATLAB 不允许两个元胞指向同一个对象,也就是说,当你令 c2 = c1
时,虽然表面上 c2 的数据和 c1 是一样的,但 MATLAB 悄悄地将 c1 的数据拷贝到了新的内存地址中,也就是 c2 指向的数据地址和 c1 指向的数据地址是不一样的。
还有许多实用的函数可以操作元胞数组,有兴趣可以看一下官方文档。
文件操作
文件操作(File IO)
使用文件有诸多优点: 首先它是被一直存储在硬盘中的,它里面储存着信息,文件可以由操作系统轻松的管理,文件同时也可以被复制和移动,可以被不同软件访问。 对于 MATLAB,它不仅可以处理其专有文件格式 (.mat .m),还可以处理 txt 文本文档、二进制文件,甚至 Excel 文件。
pwd
命令可以显示当前所在的目录 (Print Working Directory)
ls
命令可以列出当前目录下所有文件
cd
命令可以改变目录 (Change Directory)
|
|
save
命令可以保存当前工作区
load
命令可以加载当前工作区
|
|
Excel 文件操作
MATLAB 支持读取和写入 Microsoft Excel 文件。需要用到 xlsread
和 xlswrite
两个函数。
|
|
num
元素包含了表中所有的数字,txt
则是包含了文字,raw
储存了所有
|
|
至于 xlswrite
,可以写入 CSV
文件。不详细讨论了。
txt 文件操作
|
|
其中 permission 这个参数可以有很多,如:rt
wt
at
r+t
w+t
a+t
下面用一个示例来进行 txt 文件读取操作的演示。
|
|
再来看看如何写入 txt 文件。
|
|
二进制文件操作
在更多的时候,使用二进制 (binary) 文件进行文件存储和读取具有更高的效率。
下面就给出操作二进制的例子来看看 MATLAB 是如何存取二进制文件的。
|
|
下面是写入二进制文件
|
|
小结: MATLAB 提供了对常用文件类型操作的支持,使用文件,我们可以更方便地读入大量数据并进行操作,同时输出易于阅读的数据。