- 🔗 运行环境:Matlab
- 🚩 作者:左手の明天
- 🥇 精选专栏:《python》
- 🔥 推荐专栏:《算法研究》
- 📚 选自专栏:《数学建模》
- 🧿 优秀专栏:《Matlab神经网络案例分析》
目前持续更新的专栏:
- 🥇 专栏:Matlab GUI编程技巧
- 🔥 专栏:Matlab从无到有系列
- 📚 专栏:《数学建模》
💗 大家好,我是左手の明天!💗
📆 最近更新:2022 年 3 月31 日,左手の明天的第 213 篇原创博客
🌟🌟往期必看🌟🌟
matlab从无到有系列(六):高级图形处理功能(多窗口绘图以及花瓶绘制)
目录
⛳️1.Undefined function or variable "U"
⛳️2.Unexpected MATLAB expression.
⛳️3.Subscript indices must either be real positive integers or logicals
⛳️4.Matrix dimensions must agree
⛳️5.Function definitions are not permitted at the prompt or in scripts
⛳️6.One or more output arguments not assigned during call to '...'
⛳️7.??? Index exceeds matrix dimensions.
⛳️8.In an assignment A(I) = B, the number of elements in B and I must be the same
M文件其实是一个像命令集一样的ASCII(纯文本) 码文件。正是M文件的这个特点造就了MATLAB 强大的可开发性和可扩展性。
M文件的两种形式:
- 命令式(M_Script)
- 函数式(Function)
命令式文件就是命令行的简单叠加,MATLAB会 自动按顺序执行文件中的命令。
函数式文件主要用以解决参数传递和函数调用的 问题。
🚩M-script 文件的编写💗
一般过程:
- 新建M文件
- 编写指令
- 调试运行
用户在编制此类文件时,只需把所要执行的命令 按行编辑到指定的文件中,程序运行时,MATLAB按行执行这些指令。
规则:
- 建立好的书写风格,保持程序的可读性;
- m为文件的扩展名,在低版本的MATLAB中 还要注意文件名不超过8位,文件名和变量的命 名规则相同;
- 以符号%引导的行是注释行、不可执行, 可供heIp命令查询;
- 不需要用end语句作为M文件的结束标志;
- 在运行此函数之前,需要把它所在目录加到MATLAB的搜索路径上去或将文件所在目录设为当前日录。新版本会提示,老版本则出错。
- 运行一个程序,有多种方式。
🚩MATLAB控制流💗
🌻for循环结构⭐️
for循环语句的一 般格式如下:
for v = expression (表达式)
commands (执行语勾)
end
🌻while 循环结构⭐️
while循环语句的一 般格式如下:
While expression(条件式)
statements
End
例如1:用循环求解
>>s=0;
for i=1:100
s=s+i;
end
>>s=0;i=1;
while i<=100
s=s+i;
i=i+1;
end
不用循环的方法:s=sum(1:100)
例如2:用循环求解求最小的 m,
在这种情况下,最好用while.
s=0;i=0;
while s<=10000
i=i+1;
s=s+i;
end
[s, i]
🌻if-else-end 结构⭐️
循环语句的一 般格式如下:
if logical expression
statements
end
或者
if logical expression
statements 1
else
statements 2
end
或者
if logical expression 1
statements 1
elseif logical expression 2
statements 2
else
statements 3
end
例如:编写M文件求
>> A=[];
for k=1:5
for j=1:5
if k==j
A(k,k)=5;
elseif abs(k-j)==1
A(k,j)=1;
else
A(k,j)=0;
end
end
end
🌻分支语句switch-case-otherwise⭐️
循环语句的一 般格式如下:
Switch expression
case case_1
(commands 1)
case case_2
(commands 2)
……
case case_k
(commands k)
otherwise,
(commands)
end
📣📣📣
注意 :在执行过程中,只执行一个case后面的命令并跳出开关, 程序在end后继续执行。
例如:检测掷一次骰子所得的点数是单数还是双数
switch result
case{1,3,5}
disp('odd numbers')
case{2,4,6}
disp('even numbers')
otherwise
disp ('mistake!')
end
📜分支语句和C语言的区别:
- 当开关表达式的值等于某表达式,执行该语句 后结束该结构,不用 break
- otherwise 语句,不是 default
- 程序的执行结果和各个case顺序无关
- case 语句中条件不能重复,否则列在后面的条件将不能执行
🌻try-catch 结构⭐️
循环语句的一 般格式如下:
try
(commands1)-----该命令总被执行,若正确,则跳出此结构
catch
(commands2)-----仅当组命令1出现执行错误,才执行该命令
end
说明break语句和return语句的用法:
break语句用于终止for循环和while循环的执行。如果遇到break语句,则退出循环体,继续执行循环体外的下一行语句。在嵌套循环中,break只存在于最内层的循环中。
return语句用于终止当前的命令序列,并返回到调用的函数或键盘,也用于终止keyboad方式,在MATLAB中,被调用的函数运行结束后会自动返回调用函数,使用return语句时将return插入被调用函数的某一位置,根据某种条件迫使被调用函数提前结束并返回调用函数。
典例总结:
1、有一组学生的考试成绩(见表),根据规定,成绩在100分时为满分,成绩在90~99之间时为优秀,成绩在80~89分之间时为良好,成绩在60~79分之间为及格,成绩在60分以下时为不及格,编制一个根据成绩划分等级的程序。
学生姓名 | 王 | 张 | 刘 | 李 | 陈 | 杨 | 于 | 黄 | 郭 | 赵 |
成 绩 | 72 | 83 | 56 | 94 | 100 | 88 | 96 | 68 | 54 | 65 |
Name=['王','张','刘','李','陈','杨','于','黄','郭','赵'];
Marks=[72,83,56,94,100,88,96,68,54,65];
% 划分区域:满分(100),优秀(90-99),良好(80-89),及格(60-79),不及格(<60)。
n=length(Marks);
for i=1:n
a{i}=89+i;
b{i}=79+i;
c{i}=69+i;
d{i}=59+i;
end;
c=[d,c];
% 根据学生的分数,求出相应的等级。
for i=1:n
switch Marks(i)
case 100 %得分为100时
Rank(i,:)=' 满分';
case a %得分在90~99之间
Rank(i,:)=' 优秀';
case b %得分在80~89之间
Rank(i,:)=' 良好';
case c %得分在60~79之间
Rank(i,:)=' 及格';
otherwise %得分低于60。
Rank(i,:)='不及格';
end
end
% 将学生姓名,得分,级等信息打印出来。
disp(' ')
disp(['学生姓名 ',' 得分 ',' 等级']);
disp('--------------------------')
for i=1:10;
disp([' ',Name(i),' ',num2str(Marks(i)),' ',Rank(i,:)]);
end
学生姓名 得分 等级
-----------------------------------------
王 72 及格
张 83 良好
刘 56 不及格
李 94 优秀
陈 100 满分
杨 88 良好
于 96 优秀
黄 68 及格
郭 54 不及格
赵 65 及格
2、编写一段程序,能够把输入的摄氏温度转化成华氏温度,也能把华氏温度转换成摄氏温度。
k=input('选择转换方式(1--摄氏转换为华氏,2--华氏转换为摄氏):');
if k~=1 & k~=2
disp('请指定转换方式')
break
end
tin=input('输入待转变的温度(允许输入数组):');
if k==1
tout=tin*9/5+32; % 摄氏转换为华氏
k1=2;
elseif k==2
tout=(tin-32)*5/9; % 华氏转换为摄氏
k1=1;
end
str=[' C';' F'];
disp(['转换前的温度', ' ', '转换后的温度'])
disp([' ',num2str(tin),str(k,:), ' ', num2str(tout),str(k1,:)])
🚩交互式输入💗
🌻用户输入提示命令input⭐️
input 命令用来接收用户从键盘输入数据、字符串或表达式,并接收输入值。其常用格式:
R=input ('How many apples')
运行此命今后,将给出文字提示,并等待键盘输入。
R=input('what is your name ?','s')
运行此命令后,MATLAB将等待输入,并把输入 当做字符串,赋给变量R。
🌻等待用户反应命令pause⭐️
此命令用于使程序暂时终止运行,等待用户按任 意键后继续运行。
此函数的调用形式如下:
Pause 暂停程序等待回应;
Pause(n) 程序运行中等待n秒后继续运行;
Pause on 显示其后的 Pause命令,并且执行pause命令;
Pause off 显示其后的pause命令,但不执行该命令。
🌻中断命令break⭐️
break语句常常用在循环语句中。通过使用break语句,可不必等待循环的自然结束,而根据循环只设的条件来判断是否跳出循环。
🌻等待键盘输入 keyboard⭐️
使程序进入暂时等待状态,但并没退出执行,可以修改参数,和运行其他指令等。
🌻显示文字或数组 disp⭐️
如何定义全局变量?
用关键字global可以把一个变量定义为全局变量,在M文件中定义全局变量时,如果在当前工作空间已经存在了相同的变量,系统将会给出警告,说明由于将该变量定义为全局变量,可能会使变量的值发生改变,为避免发生这种情况,应该在使用变量前先将其定义为全局变量。
keyboard命令的作用是什么?当在函数中使用keyboard命令时,是否可以在工作空间浏览器中观察和修改函数中的局部变量?退出keyboard状态的命令是什么?编一个函数文件,在其中设置keyboard,观察变量情况。
当运行中的程序遇到keyboard命令时会暂时停止运行,将控制权交给键盘,这时命令窗口的提示符变为K>>,可以在命令窗口或工作空间浏览器中观察和修改变量内容,如果keyboard命令设置在函数中,则可以观察和修改函数中的局部变量,检查或修改完成后,键入return命令,退出keyboard状态,控制权交还给系统,程序将继续运行。
🚩MATLAB 函数的编写💗
M-script 适合于小规模
🌻函数的基本结构⭐️
函数定义行(关键字function)
function[out1,out2,..]=funcname(in1,in2,..)
注释段
输入返回变量的检测
函数体语句
输入和输出(返回)的参数个数分别由nargin和nargout 两个MATLAB保留的变量来给出。
📢📢📢
注意:若一个function作为一个M文件存储,切记其存储文件名应和函数名一样!
第一行帮助行
以(%)开头,作为lookfor指令搜索的行
函数体说明及有关注解
以(%)开头,用以说明函数的作用及有关内容
函数体语句
函数体内使用的除返回和输入变量这些在function语句中直接引用的变量以外的所有变量都是局部变量,即在该函数返回之后,这些变量会自动在MATLAB的工作空间中清除掉。如果希望这些中间变量成为在整个程序中都起作用的变量,则可以将它们设置为全局变量。
例如1: 若最大值不为 10000,需修改程序对 m 和 10000 值的设置,不适合于M-script.
1、定义 findsum.m文件
function [s,m]=findsum(k)
s=0;
m=0;
while(s<=k)
m=m+1;
s=s+m;
end
2、在command window中调用:
[s,m]=findsum(10000)
例如2: 函数的递归调用:阶乘 n!=n(n-1)!
1、定义fact.m文件
function k=fact(n)
if n>1
k=n*my_fact(n-1);
elseif n==0|n==1
k=1;
else
error(' input a wrong parameter!')
end
2、在command window中调用:
num=fact(11)
MATLAB函数为:prod(1:1000)
使用tic和toc函数, 测试一下该函数的运行效率,显式程序运行的时间:
tic;
num=fact(500);
toc
🌻函数编写注意事项⭐️
- 函数的函数名与存储名要一致。
- 函数名首字符必须为字母。其后可为字母数字下划线等。长度小于31个字符。
- 不推荐在同一文件中,写多个函数。
- 建议每个函数单独写成一个文件,由主程序调用,主程序不要写成函数形式。
🚩程序设计的优化💗
虽然MATLAB程序语言高度集成,但由于MATLAB属于解释型语言,在执行效率方面还是存在一些不足,因此,如何优化程序,特别是在大型的运算与仿真中,是一个很重要的话题。
🌻以矩阵作为操作主体⭐️
- 循环运算是MATLAB语言的最大弱点。
- 在程序设计时应当尽可能避免循环运算,尽量用向量化的运算来代替循环操作多重循环, 将执行次数少循环的放在外环。
- 在MATLAB编程过程中应当强调对矩阵本身 整体的运算,避免对矩阵元素的操作。
- 绝大多数的循环运算是可以转换为向量运算; 尽量使用内部函数
举些简单的例子,说明c语言和matlab的区别:
例:找出数组A=[2,5,7,8,4,9,12]中,所有大于6 的元素及其下标
x=find(A>6); % 找出下标 B=A(x); % 找出所有大于6的元素
🌻数据的预定义⭐️
对存储的合理操作及管理也会提高程序运行的效率。MATLAB语言提供了一系列的函数用以管理内存。
函数名 | 说明 |
clear | 从内存中清除所有变量及函数 |
pack | 重新分配内存 |
quit | 退出MATLAB环境,释放所有内存 |
save | 把指定变量存储至磁盘 |
load | 从磁盘中调出指定变量 |
🚩程序调试💗
🌻M文件错误的种类⭐️
M文件一般有语法错误和执行错误两种:
- 语法错误发生在M文件程序代码的解释过程中, 一般是由函数参数输入类型有误或矩阵运算阶数 不符等引起的。
- 执行错误的发生是由于在程序运行过程中,出现溢出或死循环等引起的,这些错误都与程序本身有关,并且较难发现解决。
🌻处理异常的常用方法⭐️
- 避免出现NaN、Inf或空矩阵等;
- 在可能出现上述异常数值的地方提供控制语句来识别;
- 识别函数有isnan、isinf、isempty1sn等。
🌻常见的错误提示及其解决方法⭐️
⛳️1.Undefined function or variable "U"
中文解释:函数或变量 U 没有定义
出错原因:函数或变量 U 没有定义
解决办法:仔细检查错误所指向的位置,寻找没有定义的函数或者变量,加以定义。
⛳️2.Unexpected MATLAB expression.
中文解释:不规范的matlab表达式
出错原因:少了运算符号,或者括号等情况
解决办法:仔细检查错误所指向的位置,检查是否少了乘号,或者逗号、分号、括号等。
⛳️3.Subscript indices must either be real positive integers or logicals
中文解释:下标索引必须是正整数类型或者逻辑类型
出错原因:在访问矩阵(包括向量、二维矩阵、多维数组,下同)的过程中,下标索引要么从 0 开始,要么出现了负数。
注:matlab 的语法规定矩阵的索引从 1 开始,这与 C 等编程语言的习惯不一样。
解决办法:自己调试一下程序,把下标为 0 或者负数的地方修正。
⛳️4.Matrix dimensions must agree
中文解释:矩阵的维数必须一致
出错原因:这是由于运算符(= + - / * 等)两边的运算对象维数不匹配造成的,典型的出错原因是错用了矩阵运算符。matlab 通过“.”来区分矩阵运算和元素运算。
解决办法:自己调试一下程序,保证运算符两边的运算对象维数一致。
⛳️5.Function definitions are not permitted at the prompt or in scripts
中文解释:不能在命令窗口或者脚本文件中定义函数
出错原因:一旦在命令窗口写 function c = myPlus(a,b),此错误就会出现,因为函数只能定义在 m 文件中。
关于脚本文件和 m 文件的区别可查阅 matlab 基础书。
简言之:
1) 如果你写成 function 的形式,那么必须写在 m 文件中,且以 function 开头(即 function 语句前不能包含其他语句,所有语句必须放在 function 中,当然,function 的定义可以有多个,各 function 之间是并列关系,不能嵌套);
2) 如果你写成脚本的形式,则既可以写在命令窗口中,也可以写在 m 文件中,但两者均不能包含 function 语句(即不能进行函数的定义)
解决办法:新建一个 m 文件,然后再进行函数的定义
⛳️6.One or more output arguments not assigned during call to '...'
中文解释:在调用...函数过程中,一个或多个输出变量没有被赋值
出错原因:函数如果带有输出变量,则每个输出在返回的时候都必须被赋值。容易出现这个错误的两个地方是:
- 在部分条件判断语句(如 if )中没有考虑到输出变量的返回值。
- 在循环迭代过程中部分变量的维数发生了变化。
解决办法:在条件判断或者执行循环之前对所使用的变量赋初值。
⛳️7.??? Index exceeds matrix dimensions.
中文解释:索引超出矩阵的范围
出错原因:在引用矩阵元素的时候,索引值超出矩阵应有的范围
解决办法:检查所定义数组的维数,和引用的范围。
⛳️8.In an assignment A(I) = B, the number of elements in B and I must be the same
中文解释:在赋值语句 A(I) = B 中,B 和 I 的元素个数必须相同
出错原因:矩阵维数不匹配,如矩阵乘法要求第一个矩阵的列数和第二个矩阵的行数相等。
解决办法:自己设置断点调试一下,看看 I 和 B 的维数、大小是否相同,不同的话就要修改成两者一致
还有一些隐性的错误,matlab不会报错也不会警告,但会造成结果的错误
比如由于 C 或 C++ 留下的编程习惯,我们常常会以i,j作为循环变量,但同时matlab中i,j又是复数单位,这样就会由于使用不慎,i,j被matlab认定为复数而造成结果错误。
如以下例子
for i = 1:3
A(i) = 2i+1;
end
结果为:
A =
1.0000 + 2.0000i 1.0000 + 2.0000i 1.0000 + 2.0000i
明显不是我们所要的结果,问题出在少了个乘号,但matlab并不会报错,而认为是复数单位。
正确情况是改为:
A(i) = 2*i+1;
A =
3 5 7
但针对此情况更好的方法是不用i,j作为循环变量,比如用ii和jj作为循环变量。这样的话如果出现情况:
A(ii) = 2ii+1;
则matlab会报错,错误类型见上2。
🌻调试过程⭐️
- 在M文件中设置断点
- 巧用“;”,运行到适当的地方输出信息,帮助分析
- 单步运行,通过输出信息和workspace的变量 来查看程序是否运行正常
- 改变输入信息,查看出错症结
- 使用profile,tic,toc ,cputime函数查看文件运行耗时及各部分性能,以便化简
🌻命令文件与函数文件的区别⭐️
(1)命令文件是一系列命令的组合,函数文件的第一行必须用function说明;
(2)命令文件没有输入参数,也不用返回参数,函数文件可以接受输入参数,也可以返回参数;
(3)命令文件处理的变量为工作空间变量,函数文件处理的变量为函数内部的局部变量,也可以处理全局变量。