我终于不得不对MATLAB下手了

我终于不得不对MATLAB下手了,没办法,要参加建模了,本来以为我的博客写的又没逻辑又垃圾,没想到还有很多人看呢,不得不好好写了,这篇博客是在建模前写的,不过一直拖到建模结束才发出来(笑哭,我真是拖延症患者),介于我对这种语言也是新手,学这个也暂时只是为了建模,寒假期间会继续更新机器学习和Python内容。

以上。

这篇文章适合会一些别的语言,但是MATLAB完全小白(就像我一样)的同学们看。所有内容均来自网络,大部分会注明来源,如有遗漏还望指出。

https://www.w3cschool.cn/matlab/matlab-5use28gb.html这个是一个教程,我先去瞄一眼基本语法,应该和其他语言差距不大。

一、一些基本的语法

除了一些和其他语言差不多的语法之外,还有一些我比较在意的部分:

octave:2> a=[1 2 3 4 5 6 7 8 9];b=[4 4 4 4];
octave:3> a+b
error: operator +: nonconformant arguments (op1 is 1x9, op2 is 1x4)
octave:3> a+b'
ans =
 
    5    6    7    8    9   10   11   12   13
    5    6    7    8    9   10   11   12   13
    5    6    7    8    9   10   11   12   13
    5    6    7    8    9   10   11   12   13

就是矩阵的计算规则……

MATLAB中分号(;)表示语句结束;但是,如果想抑制和隐藏 MATLAB 输出表达,表达后添加一个分号。

MATLAB的百分比符号(%)是用于表示一个注释行。

MATLAB支持以下特殊变量和常量:

Name

Meaning

ans

默认的变量名,以应答最近依次操作运算结果

eps

浮点数的相对误差

i,j

虚数单位,定义为 i2 = j2 = -1

Inf

代表无穷大

NaN

代表不定值(不是数字)

pi

圆周率

MATLAB常用的运算符和特殊字符如下表所示:

运算符

目的

+

加;加法运算符

-

减;减法运算符

*

标量和矩阵乘法运算符

.*

数组乘法运算符

^

标量和矩阵求幂运算符

.^

数组求幂运算符

\

矩阵左除

/

矩阵右除

.\

阵列左除

./

阵列右除

:

向量生成;子阵提取

( )

 下标运算;参数定义 

[ ]

矩阵生成

.

点乘运算,常与其他运算符联合使用

续行标志;行连续运算符

,

分行符(该行结果不显示)

;

语句结束;分行符(该行结果显示)

%

注释标志

_

引用符号和转置运算符

._

非共轭转置运算符

=

赋值运算符

下表显示了MATLAB中最常用的数据类型:

数据类型

描述

int8

8位有符号整数

uint8

8位无符号整数

int16

16位有符号整数

uint16

16位无符号整数

int32

32位有符号整数

uint32

32位无符号整数

int64

64位有符号整数

uint64

64位无符号整数

single

单精度数值数据

double

双精度数值数据

logical

逻辑值为1或0,分别代表true和false

char

字符数据(字符串作为字符向量存储)

单元格阵列

索引单元阵列,每个都能够存储不同维数和数据类型的数组

结构体

C型结构,每个结构具有能够存储不同维数和数据类型的数组的命名字段

函数处理

指向一个函数的指针

用户类

用户定义的类构造的对象

Java类

从Java类构造的对象

其他的还是看https://www.w3cschool.cn/matlab/matlab-5use28gb.html这里吧,写的挺清楚的(笑哭),然后还有很正常的各种循环什么的,乍一看和C++啊、C啊、Python啊没什么差别,大家就发挥一下举一反三的精神叭。

对了,还有一个我比较在意的就是for循环那里。

在MATLAB中建立一个脚本文件,并输入下述代码:

for a = 10:20

  fprintf('value of a: %d

', a);

end

运行文件,显示下述结果:

value of a: 10

value of a: 11

value of a: 12

value of a: 13

value of a: 14

value of a: 15

value of a: 16

value of a: 17

value of a: 18

value of a: 19

value of a: 20

在MATLAB中建立一个脚本文件,并输入下述代码:

for a = 1.0: -0.1: 0.0

   disp(a)

end

运行该文件,显示以下结果:

1

 

    0.9000

 

    0.8000

 

    0.7000

 

    0.6000

 

    0.5000

 

    0.4000

 

    0.3000

 

    0.2000

 

    0.1000

 

     0

在MATLAB中建立一个脚本文件,并输入下述代码:

for a = [24,18,17,23,28]

   disp(a)

end

运行该文件,显示下述结果:

    24

 

    18

 

    17

 

    23

 

28

现在MATLAB中建立一个脚本文件,并输入下述代码:

for i=2:100

       for j=2:100

        if(~mod(i,j))

            break; % if factor found, not prime

        end

      end

      if(j > (i/j))

          fprintf('%d is prime

', i);

      end

end

然后运行该文件,显示如下结果:

2 is prime

3 is prime

5 is prime

7 is prime

11 is prime

13 is prime

17 is prime

19 is prime

23 is prime

29 is prime

31 is prime

37 is prime

41 is prime

43 is prime

47 is prime

53 is prime

59 is prime

61 is prime

67 is prime

71 is prime

73 is prime

79 is prime

83 is prime

89 is prime

97 is prime

 

我比较好奇那个冒号的用法到底是什么,在后面画图里面也有用到的,所以比较在意。

反正在这里应该就是相当于from to,然后step=1,酱紫。

哦,我又发现了一个,应该会好理解一些了

在MATLAB中建立一个脚本文件,代码如下:

v = [1: 2: 20];

sqv = v.^2;

disp(v);disp(sqv);

运行该文件,显示结果如下:

1     3     5     7     9    11    13    15    17    19

1     9    25    49    81   121   169   225   289   361

就是从1到20,每次加2。

要是按C++语法写就应该是:

for(i=1;i<20;i=i+2)

 

二、MATLAB中常用到的数学函数和矩阵

首先,先说明一点,如果我们不给变量命名,MATLAB会自动给她起名叫——ans,就像这样:

octave:2> abs(-12)

ans =  12

这里函数abs(x)和其他语言一样,就是取绝对值(可能称之为模长更加合适一些)

这倒不是什么要紧的事,这里提一下关于复数:

octave:3> x=2+5i
x =  2 + 5i
octave:4> real(x)
ans =  2
octave:5> imag(x)
ans =  5
octave:6> conj(x)
ans =  2 - 5i
octave:7> angle(x)
ans =  1.1903
octave:8> abs(x)
ans =  5.3852

这里,2+5i就是构造了一个复数,real(x)就是取复数的实部,imag(x)就是取复数的虚部,conj(x)是取共轭复数,angle(x)是取相角,abs(x)在这里就是求模长了。

当然MATLAB也可以四舍五入什么的,比如:

octave:2> x=1.67
x =  1.6700
octave:3> floor(x)
ans =  1
octave:4> ceil(x)
ans =  2
octave:5> round(x)
ans =  2
octave:6> fix(x)
ans =  1
octave:7> rat(x)
ans = 2 + 1/(-3 + 1/(-33))
octave:8> rats(x)
ans =   167/100
octave:9> sign(x)
ans =  1

我们先定义一个x=1.67,然后floor(x)取小于x的最大整数,ceil(x)取大于x的最小整数,round(x)负责四舍五入,rat(x):将R = rat(X) 返回 X 在默认容差 1e-6*norm(X(:),1) 内的有理分式近似值。近似值是一个包含截断的连分式展开项的字符向量(https://ww2.mathworks.cn/help/matlab/ref/rat.html#bt8x97b-1),还可以增加精度,具体看括号里官方文档。

下面是做一个对比,负数的情况:

octave:2> y=-1.67
y = -1.6700
octave:3> floor(y)
ans = -2
octave:4> ceil(y)
ans = -1
octave:5> round(y)
ans = -2
octave:6> fix(y)
ans = -1
octave:7> rat(y)
ans = -2 + 1/(3 + 1/33)
octave:8> rats(y)
ans =  -167/100
octave:9> sign(y)
ans = -1

然后还有就是一些具体的函数了,比如三角函数什么的,具体可以参考https://www.cnblogs.com/carl2380/p/6237126.html的总结,在此不做赘述。

接下来就是矩阵部分了:

octave:2> a=[1 2 3 4 5;6 7 8 9 10;11 12 13 14 15]
a =
 
    1    2    3    4    5
    6    7    8    9   10
   11   12   13   14   15
 
octave:3> a'
ans =
 
    1    6   11
    2    7   12
    3    8   13
    4    9   14
    5   10   15

其实我线性代数学得也不怎么样,而且好久没碰了,如果叫的名字不对大家见谅。首先很明显,矩阵a中“1 2 3 4 5”是行向量,用分号隔开每一行,在a后面加上一个单引号,就变成了矩阵a的转置ans矩阵,在这里“1 2 3 4 5”就是列向量了。

下面是一个错误:

octave:2> b=[1 2 3 4 5;6 7]
error: vertical dimensions mismatch (1x5 vs 1x2)

与其他语言不同,这里不会直接给没填完的矩阵添0,一定要注意。

octave:2> x=2333
x =  2333
octave:3> x*2+1
ans =  4667
octave:4> y=[1 2 3 4 5;9 8 7 6 10]
y =
 
    1    2    3    4    5
    9    8    7    6   10
 
octave:5> y*2+1
ans =
 
    3    5    7    9   11
   19   17   15   13   21

与普通的数字一样,我们也可以对矩阵进行运算。

octave:6> y*y
error: operator *: nonconformant arguments (op1 is 2x5, op2 is 2x5)
octave:6> y*y'
ans =
 
    55   120
   120   330

这里和线性代数里一样,大家注意矩阵运算法则(反正我感觉我是白学了)

octave:7> y(3)
ans =  2
octave:8> y(3)=23333
y =
 
       1   23333       3       4       5
       9       8       7       6      10

前一个是输出第三个元素(?),后一个是修改第三个元素(?)。

octave:9> length(y)
ans =  5
octave:10> max(y)
ans =
 
       9   23333       7       6      10
 
octave:11> min(y)
ans =
 
   1   8   3   4   5

看起来这些函数都是针对一个向量的,一个是求长度,一个是最大值,最后一个是求最小值。

嗯,查了一下确实是向量,然后还有其他的部分,也参见https://www.cnblogs.com/carl2380/p/6237126.html吧,在这里也不赘述了,大家可以一个一个试一试。

好了,我们再说回复数的问题,他还有一些其他的操作:

octave:2> are=[1 0 -1;23 -2 6]
are =
 
    1    0   -1
   23   -2    6
 
octave:3> aim=[2 1 0;0 -1 -1]
aim =
 
   2   1   0
   0  -1  -1
 
octave:4> a=are+aim
a =
 
    3    1   -1
   23   -3    5
 
octave:5> a=are+aim*i
a =
 
    1 +  2i    0 +  1i   -1 +  0i
   23 +  0i   -2 -  1i    6 -  1i

可以看到,这里构造含有复数的矩阵就是把复数部分乘以i。

三、画图

蹡蹡,下面就是本手残最感兴趣的画图环节(我什么时候才能成为大触啊)

听说还有别的软件可以画图,像我之前在学的Python也可以用来画图,还有那些画画特别好看的小姐姐用的画图软件(滑稽)也可以画图。

我们先看看结果,过个瘾,然后我们再来说原理之类的(其实是我个人想先过个瘾)。

程序如下:在命令窗口中输入以下命令  

>> x=0:pi/100:2*pi;

>> y=2*exp(-0.5*x).*sin(2*pi*x);

>> plot(x,y)

结果如下:

 

代码来自https://blog.csdn.net/qing101hua/article/details/78425567

https://blog.csdn.net/weixin_42081343/article/details/80942649这个是有人做的小结,就是画图相关的命令,我也在这里mark一下。

>> t=-pi:pi/100:pi;

>> x=t.*cos(3*t);

>> y=t.*sin(t).*sin(t);

>> plot(x,y)

 

三维的图:

t=0:pi/50:2*pi;

x=8*cos(t);

y=4*sqrt(2)*sin(t);

z=-4*sqrt(2)*sin(t);

plot3(x,y,z,'p');

 

 

 

 

 

 

octave:2> m=30;
 
z=1.2*(0:m)/m;
 
r=ones(size(z));
 
theta=(0:m)/m*2*pi;
 
x1=r'*cos(theta);y1=r'*sin(theta);%生成第一个圆管的坐标矩阵
 
z1=z'*ones(1,m+1);
 
x=(-m:2:m)/m;
 
x2=x'*ones(1,m+1);y2=r'*cos(theta);%生成第一个圆管的坐标矩阵
 
z2=r'*sin(theta);
 
surf(x1,y1,z1);          %绘制竖立的圆管
 
axis equal ,axis off
 
hold on
 
surf(x2,y2,z2);          %绘制平放的圆管
 
axis equal ,axis off
 
title ('两个等直径圆管的交线');
 
hold off

 

 

 

 

 

 

 

-------------------------好了,体验结束

先是补充一个我刚刚看到的东西

 

为了玩这个画图,我准备找隔壁学院学MATLAB的同学借一下他们课设的题目。

又注意到了图论(笑哭,怎么哪里都有这个鬼东西),那就索性做一个这方面的叭。这次选择的是大家都很熟悉的 迪克斯特拉(Dijkstra)算法(不知道为什么我一直习惯叫他迪士尼算法,不过这个不重要)https://www.cnblogs.com/wt20/p/5730419.html以及这个

 

这种算法在图论里呢,应该算是很有名的叭,就……

所谓迪克斯特拉算法呢,就是适合用来求解单源最短路的题(突然有点迷糊关于这个和深搜广搜),就是从一个固定的顶点向外走,走的方式有很多,但是每一种方式的权重或者说代价是不同的,所以理所当然的,我们就要找出又快又好的方式,然后就引入了这种算法,酱紫。然后方法呢,就是建立一个矩阵(划重点!矩阵!是不是特别符合今天的主题,滑稽),用矩阵记录从一点到另一点的代价,如果两点是不通的,那么当然代价就是∞了。

https://blog.csdn.net/qq_39521554/article/details/79333690这里可以补一下简单的算法介绍,就不赘述啦。

例题:

 某公司在六个城市c1, c2,,,, c6 中有分公司,从 ci到 cj 的直接航程票价记在 
下述矩阵的 (i, j) 位置上。(∞ 表示无直接航路),请帮助该公司设计一张城市 c1 到其它城市间的票价最便宜的路线图。 (https://blog.csdn.net/u013414501/article/details/50506907/

首先,这个矩阵,一看就是无向图(以主对角线为对称轴,两边完全对称)。以往在acm常出的题中,我们要做的就是把题目信息整理成这样的矩阵,那么,如果我们已经有了这个矩阵,当然就可以直接找最短的向量了。

clc,clear all

a=zeros(6);

a(1,2)=50;a(1,4)=40;a(1,5)=25;a(1,6)=10;              

a(2,3)=15;a(2,4)=20;a(2,6)=25;

a(3,4)=10;a(3,5)=20;

a(4,5)=10;a(4,6)=25;

a(5,6)=55;

a=a+a'                                                 

a(find(a==0))=inf %将a=0的数全部替换为∞(即INF)              

pb(1:length(a))=0;pb(1)=1;  %当一个点已经求出到原点的最短距离时,其下标i对应的pb(i)赋1(pb在这里离就是相当于C++里经常出现的标记数组而已)

index1=1; %存放存入S集合的顺序

index2=ones(1,length(a)); %存放始点到第i点最短通路中第i顶点前一顶点的序号

d(1:length(a))=inf;d(1)=0;  %存放由始点到第i点最短通路的值

temp=1;  %temp表示c1,算c1到其它点的最短路。

while sum(pb)<length(a)  %看是否所有的点都标记为P标号

tb=find(pb==0); %找到标号为0的所有点,即找到还没有存入S的点

d(tb)=min(d(tb),d(temp)+a(temp,tb));%计算标号为0的点的最短路,或者是从原点直接到这个点,又或者是原点经过r1,间接到达这个点

tmpb=find(d(tb)==min(d(tb)));  %求d[tb]序列最小值的下标

temp=tb(tmpb(1));%可能有多条路径同时到达最小值,却其中一个,temp也从原点变为下一个点

pb(temp)=1;%找到最小路径的表对应的pb(i)=1

index1=[index1,temp];  %存放存入S集合的顺序

temp2=find(d(index1)==d(temp)-a(temp,index1));

index2(temp)=index1(temp2(1)); %记录标号索引

end

d, index1, index2

输出情况:

a =

 

     0    50     0    40    25    10

    50     0    15    20     0    25

     0    15     0    10    20     0

    40    20    10     0    10    25

    25     0    20    10     0    55

    10    25     0    25    55     0

 

 

a =

 

   Inf    50   Inf    40    25    10

    50   Inf    15    20   Inf    25

   Inf    15   Inf    10    20   Inf

    40    20    10   Inf    10    25

    25   Inf    20    10   Inf    55

    10    25   Inf    25    55   Inf

 

 

d =

 

     0    35    45    35    25    10

 

 

index1 =

 

     1     6     5     2     4     3

 

 

index2 =

 

     1     6     5     6     1     1

除了之前写过的基本的语法和函数以外,这里再针对这段代码补充一些。

  • find():

find(X):返回向量或数组不为零元素的位置索引。

 find(X,k,'first'):返回前k个不为零元素的位置索引。

find(X,k,'last'):返回后k个不为零元素的位置索引。

  • length():数组长度

https://www.cnblogs.com/xuliangxing/p/7373506.html

嗯,差不多就这样了,大体上思想并没有改变,就是换了一种语言(当然像我这样的记性,板子是背不掉的,这辈子都背不掉了)

好了,这个入门的坑我就已经填完了!

记录一下时间,然后我去开建模算法的坑了,挥挥。

最后祝大家2019年一切顺利

 

 

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值