【MATLAB学习笔记】导航&资源&笔记
在Coursera上学习MATLAB课程的过程中,自己把笔记整理总结了一下,一方面方便自己日后的参考,另一方面也提供给大家一些资源和经验。
修改一下第一行:
进行判断后返回值为1(真)或0(假)
可以进行一组数的比较
非零为真,零为假
是指函数可以根据输入输出的表达式个数和类型作出不同的反应。
举个栗子:
MATLAB中许多内置的函数是多态的(sqrt, max, size, plot, etc.)
如何使自己的函数具有多态性?
重置:
同其他的编程语言一样,MATLAB也有许多的数据类型。下面我们来看看我们用过哪些数据类型。
在MATLAB中,字符串其实是一个向量,其中的元素自然是字符(char),字符又是由ASCII码值,可以得到一个打印所有可见字符的例子:
具体使用方法可以参考MATLAB自带的WIKI
注:
结构体和数组的区别:
下面来实践一下:
结构体数组:在已经定义了一个结构体的前提下,可以快速构造结构体数组。已知
在一个结构体数组中,如果一个结构体的字段是一个子结构体,那么这两个子结构体不一定要相同。
注意:在使用
注意:MATLAB不允许两个元胞指向同一个对象,也就是说,当你令
还有许多实用的函数可以操作元胞数组,有兴趣可以看一下官方文档。
使用文件有诸多优点: 首先它是被一直存储在硬盘中的,它里面储存着信息,文件可以由操作系统轻松的管理,文件同时也可以被复制和移动,可以被不同软件访问。 对于MATLAB,它不仅可以处理其专有文件格式(.mat .m),还可以处理txt文本文档、二进制文件,甚至Excel文件。
下面用一个示例来进行txt文件读取操作的演示。
下面就给出操作二进制的例子来看看MATLAB是如何存取二进制文件的。
MATLAB程序设计入门
【前言】这一部分偏重的是基于MATLAB的程序设计,即编程的方法,当然也包含了很多MATLAB的基础操作。个人觉得,之后对MATLAB一些工具的使用在有了MATLAB的编程基础的前提下回变得相对的轻松。我是在15年下半年(大一)在Coursera学习了这一门课MATLAB 程序设计入门,英文课程,总体难度不大,毕竟是针对初学者的课程。但有一些章节的课后作业还是挺有难度的。 下面是我在学习这一课程过程中的笔记,因为是在课余学习的,只记了关键的一些操作与命令。考虑会在后续补上截图与操作。
MATLAB应用
后续不断补充
Mathworks官方资源
在线入门教程(英文) 英文PDF文档(需登录) 官方PDF网盘下载 MATLAB百度云下载矩阵的操作
克隆运算符(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 9x(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
编辑新文件function myRand
a=1+rand(3,4)*9
end
保存为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里。
将函数修改一下function a=myRand(low, high)
a=low+rand(3,4)*(high-low);
end
就可以输出在low~high之间的随机数表了。若想输出a中的全部数字的和,则可以改成如下function [a,s]=myRand(low, high)
a=low+rand(3,4)*(high-low);
v=a(:);
s=sum(v);
end
然后在命令行中输入[x ss]=myRand(1,10)
就会分别输出数表x及所有数字之和ssfunction的定义
funtion [out-arg1, out-arg2, ...]
=function-name(in-arg1, in-arg2, ...)
不确定函数名是否已定义,可以用help exist
subfunction-定义多个(子)函数
举个栗子function [a, s] = myRand(low, high)
a = low+rand(3,4)*(high-low)
s = sumAllElements(a);
function summa = sumAllElements(M)
v = M(:);
summa = sum(v);
全局变量
global v;
v=(...);
一定要分开写
新手尽量少使用,可能会导致难检测的错误。function的优点
- 将一个大问题分解
- 功能的分解
- 代码复用
- 普遍性
Script-脚本
是一个.m
文件,用来执行一系列命令、赋值等计算
执行脚本时只需输名字fprint('This is matlab\n');
pause(5);
quit;
分支结构
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语句
function guess_my_number(x)
if x == 2
fprintf('Congrats! You guessed my number!\n');
elseif x < 42
fprintf('Too small. Try again\n');
else
fprintf('Not right, but a good guess.\n');
end
最后一个else可以不要,就是一个if-elseif结构。关系运算符(Relational operators)
运算符 | 含义 |
---|---|
== | 判断是否等于 |
~= | 是否不等于 |
> | 是否大于 |
< | 是否小于 |
>= | 是否大于等于 |
<= | 是否小于等于 |
进行判断后返回值为1(真)或0(假)
可以进行一组数的比较
[4 -1 7 5 3] > [5 -9 6 5 -3]
ans =
0 1 1 0 1
当然也可以这样,逐个与4进行比较:[4 -1 7 5 3] <= 4
还有很多玩法sum([14 9 3 14 8 3] == 14)
逻辑运算符(Logical operators)
运算符 | 含义 |
---|---|
&& | 逻辑与 |
| | 逻辑或 |
~ | 逻辑非 |
输入 | && | || | |
---|---|---|---|
false | false | 0 | 0 |
false | true | 0 | 1 |
true | false | 0 | 1 |
true | true | 1 | 1 |
非零为真,零为假
~[1 pi 0 -2]
ans =
0 0 1 0
但对两个矩阵使用&&
和||
,应变为&
和|
[1 -3 0 9 0] & [pi 0 0 2 3]
ans =
1 1 0 1 1
help precedence
获取关于运算符优先级的帮助循环嵌套(Nested if-statements)
if arg_1
if arg_2
statement_1;
else
statement_2;
end
else
statement_3;
end
多态函数
多态函数(Polymorphic functions)
什么是多态?是指函数可以根据输入输出的表达式个数和类型作出不同的反应。
举个栗子:
zeros(5,6)
生成5×6矩阵,zeros(4)
生成4×4的矩阵。MATLAB中许多内置的函数是多态的(sqrt, max, size, plot, etc.)
如何使自己的函数具有多态性?
nargin: 返回实际的输入参数的个数
nargout: 返回实际要求的输出参数个数下面这个函数
multable(n,m)
生成n×m的数阵,我们来使其具有多态性function [table summa] = multable(n,m)
if nargin < 2
m = n;
end
table = (1:n)' * (1:m);
if nargout == 2
summa = sum(table(:));
end
[table s] = multable(3,4)
,会输出3×4的数表和其所有元素和table = multable(5)
,只会输出5×5数表健壮性(Robustness)
一个健壮的函数,会对各种可能出现错误的情况进行处理。上面的函数可以进行如下的优化:function [table summa] = multable(n,m)
% MULTABLE muliplication table.
% T = MULTABLE(N) return an N-by-N matrix
% containing the multiplication table for
% the integers 1 through N.
% MULTABLE(N,M) returns an N-by-M matrix.
% Both input arguments must be positive integers.
% [T SM] = MULTABEL(...) returns the matrix
% containing the multiplication table in T
% and the sum of all its elements in SM
if nargin < 1 %没有输入
error('must have at least one input argument');
end
if nargin < 2
m = n;
elseif ~isscalar(m) || m < 1 || m ~= fix(m) %参数不为正整数
error('m needs to be a positive integer');
end
if ~isscalar(n) || n < 1 || n ~= fix(n)
error('n needs to be a positive integer');
end
table = (1:n)' * (1:m);
if nargout == 2
summa = sum(table(:));
end
%后为注释,在命令行中输入help multable
,可以得到最上面一大段注释作为help的内容持续变量(Persistent variables)
和全局变量类似,但又有所区别。function total = accumulate(n)
persitent summa;
if isempty(summa)
summa = n;
else
summa = summa + n;
end
total = summa;
也就是说,再次调用这个函数的时候,summa的值是接着上次的值的。重置:
clear accumulate
输入输出和绘图
输入&输出(Input&Output)
function a = one_more
x = input('Gimme a number, buddy:');
a = x+1;
上面实现了输入一个x,并将x+1赋值给a,input括号中的为控制台输出的提示信息。fprintf('This is an output example\\n')
输出一行信息function check_out(n,price)
total = n*price;
fprintf('%d items at %.2f each\\nTotal = $%5.2f \\n',n,price,total);
fprintf中的f代表format,即格式化。%d
,整数
%.2f
,f代表fixed point,小数位为2位
%5.2
,共5位(包括小数点),小数点后2位。fprintf('%4.1f\\n',[1 2 3])
会输出1.0
2.0
3.0
绘图(Plot)
a = (1:10).^2
plot(a)
绘图一般是先生成数列,再绘图plot(t,b)
,以t为x轴,b为y轴
figure(2)
,新建第2个空白的图像,如果有就切换到这个图像x1 = 0:0.1:2*pi; y1 = sin(x1);
x2 = pi/2:0.1:3*pi; y2 = cos(x2);
plot(x1,y1,x2,y2)
自定义图像样式
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的类型。如:>> class(0)
ans =
double
whos
命令可以列出当前工作区域变量的详细信息。数字类型(Numerical Types)
双精度实数(Double)- MATLAB中默认的数据类型
- 浮点表示形式,例如:12.34 = 1234 * 10-2
- 内存占用:64 bits(8 bytes)
- 与双精度类似。
- 内存占用:32 bits(4 bytes)
- 分为有符号(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
返回是否是这个类型,例如>> isa(x,'double')
范围检测intmax
intmin
realmax
realmin
>> intmax('uint32')
类型转换int8(x)
uint32(x)
double(x)
需要说明的是,当一个变量重新赋值时,会转换为所赋值的类型。字符串(Strings)
字符串,顾名思义,是由一串字符组成的。在MATLAB中,字符串其实是一个向量,其中的元素自然是字符(char),字符又是由ASCII码值,可以得到一个打印所有可见字符的例子:
function char_codes
for ii = 33:126
fprintf('%s',char(ii));
end
fprintf('\n');
MATLAB中,有一些常用的操作字符串的函数:函数 | 作用 |
---|---|
findstr | 找到字符串中的子串 |
num2str | 将数字转换为字符串 |
str2num | 将字符串转换为数字 |
strcmp | 比较两个字符串 |
lower | 将字符串转换为小写 |
upper | 将字符串转换为大写 |
sprintf | 将结果写入字符串中 |
具体使用方法可以参考MATLAB自带的WIKI
注:
strcmp
在比较时严格区分大小写,若忽略大小写,可以用strcmpi
sprintf
的用法和fprintf
用法基本一致,但区别在于sprintf
返回一个字符串结构体类型(Structs)
众所周知,在MATLAB中,一个数列只能包含类型相同的一组数据,那我们需要存储类型不同的数据怎么办呢?结构体就能做到。结构体和数组的区别:
- 结构体的基本单位是字段(fields)而非元素(elements)
- 我们访问结构体时用的是字段名称(field name)而非索引(indices)
- 字段可以有不同的数据类型(甚至是另一个结构体)
下面来实践一下:
>> r.ssn = 12345678
%以上定义了一个结构体r
>> r.name = 'Homer Simpson'
%继续添加其它类型的字段
>> r.address.street = "742 Evergreen Terrace"
%这里的r.address就是一个子结构体
一些常用的操作结构体的函数:函数 | 作用 |
---|---|
isfield | 判断结构体中是否有字段 |
setfield | 动态添加字段 |
rmfield | 删除结构体中的一个字段 |
struct | 快速构造一个结构体 |
结构体数组:在已经定义了一个结构体的前提下,可以快速构造结构体数组。已知
account
为一个结构体>>account(2).number = 7654321;
account =
1×2 struct array with fields:
number
balance
owner
值得注意的是,在account(2)
中,除了赋过值的number
字段外,其它字段初始为空在一个结构体数组中,如果一个结构体的字段是一个子结构体,那么这两个子结构体不一定要相同。
注意:在使用
rmfield
时,应将返回值赋给要删除字段的结构体。元胞数组(Cells)
这种类型也是MATLAB独有的,类似于C语言中的指针(Pointer),但一个元胞(Cell)并不直接存内存的地址,而是指向某变量。%% The Ultimate Legend of Big John 相当于段落文本
page{1} = 'You could find him on the field almost any day.';
page{2} = 'Tall, dark hair, and eyes of steel gray.';
page{3} = 'They say he pulled a Frisbee ''bout half a mile,';
page{4} = 'And when he''d stick in the corner, you could almost catch a smile';
page{5} = 'On Big John.';
%% 打印输出
fprintf('\n');
for ii = 1:length(page)
fprintf('%s\n',page{ii});
end
fprintf('\n');
可以看出元胞数组的定义是用了一对花括号{}
,而里面的数字类似于数组的索引。此外,你可以这样构建元胞数组:p = cell{2,3}
p{1,2} = 'Awesome'
类似于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)cd('Lesson 08') %进入当前文件夹下的Lesson 08文件夹
cd('..') %返回上级目录
cd('../..') %返回上上级目录
mkdir('folder') %创建新目录
rmdir('folder') %删除空目录
save
命令可以保存当前工作区
load
命令可以加载当前工作区save my_data_file data s a %将变量a和s保存至my_data_file.mat
load my_data_file %从my_data_file.mat中加载变量
Excel文件操作
MATLAB支持读取和写入Microsoft Excel文件。需要用到xlsread
和xlswrite
两个函数。>> [num,txt,raw] = xlsread('Nashville_climate.xlsx')
num
元素包含了表中所有的数字,txt
则是包含了文字,raw
储存了所有>> temps = xlsread('Nashville_climate.xlsx') %temps包含有数字
>> [temps txt] = xlsread('Nashville_climate.xlsx')
>> [~, text] = xlsread('Nashville_climate.xlsx') %只输出text
>> [~, ~, everything] = xlsread('Nashville_climate.xlsx')
>> num = xlsread('Nashville_climate.xlsx', 1, 'D15:E17')
%数字1表示工作簿,D15指定了D15这个单元格
>> num = xlsread('Nashville_climate.xlsx', 1, 'D15:E17')
至于xlswrite
,可以写入CSV
文件。不详细讨论了。txt文件操作
fid = fopen(filename, permission);
fclose(fid);
其中permission这个参数可以有很多,如:rt
wt
at
r+t
w+t
a+t
下面用一个示例来进行txt文件读取操作的演示。
function view_text_file(filename)
fid = fopen(filename,'rt');
if fid < 0
error('error opening file %s\n', filename);
end
% Read file as a set of strings, one string per line:
oneline = fgets(fid);
while ischar(oneline)
fprintf('%s',oneline) % display one line
oneline = fgets(fid);
end
fprintf('\n');
fclose(fid);
再来看看如何写入txt文件。function write_temp_precip_txt(filename)
Title_1 = 'Climate Data for Nashville, TN';
Title_2 = '(Average highs (F), lows (F), and precip (in)';
Label_1 = ' High ';
Label_2 = ' Low ';
Label_3 = 'Precip';
Mo_1 = {'Jan','Feb','March','April','May','June'};
Mo_2 = {'July','Aug','Sep','Oct','Nov','Dec'};
Data_1 = [
46 28 3.98
51 31 3.7
61 39 4.88
70 47 3.94
78 57 5.08
85 65 4.09];
Data_2 = [
89 69 3.78
88 68 3.27
82 61 3.58
71 49 2.87
59 40 4.45
49 31 4.53];
fid = fopen(filename,'w+t');
if fid < 0
fprintf('error opening file\n');
return;
end
fprintf(fid,'%s\n',Title_1);
fprintf(fid,'%s\n',Title_2);
fprintf(fid,'\n');
fprintf(fid,' %s%s%s\n',Label_1,Label_2,Label_3);
for ii = 1:6
fprintf(fid,'%5s: ',Mo_1{ii});
fprintf(fid,'%5.2f,%5.2f,%5.2f\n',Data_1(ii,:));
end
fprintf(fid,'\n');
fprintf(fid,' %s%s%s\n',Label_1,Label_2,Label_3);
for ii = 1:6
fprintf(fid,'%5s: ',Mo_2{ii});
fprintf(fid,'%5.2f,%5.2f,%5.2f\n',Data_2(ii,:));
end
fclose(fid);
二进制文件操作
在更多的时候,使用二进制(binary)文件进行文件存储和读取具有更高的效率。下面就给出操作二进制的例子来看看MATLAB是如何存取二进制文件的。
function A = read_bin_file(filename,data_type)
fid = fopen(filename,'r');
if fid < 0
error('error opening file %s\n',filename);
end
A = fread(fid,inf,data_type);
fclose(fid);
下面是写入二进制文件function write_array_bin(A,filename)
fid = fopen(filename,'w+');
if fid < 0
error('error opening file %s\n', filename);
end
fwrite(fid,A,'double');
fclose(fid);
小结:
MATLAB提供了对常用文件类型操作的支持,使用文件,我们可以更方便地读入大量数据并进行操作,同时输出易于阅读的数据。
Comments
Post a Comment