MATLAB Language开始使用MATLAB语言


版本

发布发布日期
1.0 1984-01-01
2 1986年1月1日
3 1987年1月1日
3.5 1990-01-01
4 1992-01-01
4.2C 1994-01-01
5 第8卷 1996-12-01
5.1 第9卷 1997-05-01
5.1.1 R9.1 1997年5月2日
5.2 R10 1998-03-01
5.2.1 R10.1 1998-03-02
5.3 R11 1999-01-01
5.3.1 r11.1的 1999-11-01
6 R12 2000-11-01
6.1 R12.1 2001-06-01
6.5 R13 2002-06-01
6.5.1 R13SP2 2003-01-01
6.5.2 R13SP2 2003-01-02
7 R14 2006-06-01
7.0.4 R14SP1 2004-10-01
7.1 R14SP3 2005-08-01
7.2 R2006a 2006-03-01
7.3 R2006b 2006-09-01
7.4 R2007a 2007-03-01
7.5 R2007b 2007-09-01
7.6 R2008a 2008-03-01
7.7 R2008b 2008-09-01
7.8 R2009a 2009-03-01
7.9 R2009b中 2009-09-01
7.10 R2010a版本 2010-03-01
7.11 R2010b中 2010-09-01
7.12 R2011a 2011-03-01
7.13 R2011b 2011-09-01
7.14 R2012a 2012-03-01
8 R2012b 2012-09-01
8.1 R2013a 2013-03-01
8.2 R2013b 2013年9月1日
8.3 R2014a 2014年3月1日
8.4 R2014b 2014年9月1日
8.5 R2015a 2015年3月1日
8.6 R2015b 2015年9月1日
9 R2016a 2016年3月1日
9.1 R2016b 2016年9月14日
9.2 R2017a 2017年3月8日

另请参阅: Wikipedia上的MATLAB版本历史记录

匿名函数和函数句柄

基本

匿名函数是MATLAB语言的强大工具。它们是本地存在的函数,即:在当前工作空间中。但是,它们不像常规函数那样存在于MATLAB路径中,例如在m文件中。这就是为什么它们被称为匿名,尽管它们可以在工作区中具有类似变量的名称。

@ 运营商

使用@ 运算符创建匿名函数和函数句柄。例如,要创建sin 函数的句柄(正弦)并将其用作f

>> f = @sin
f = 
    @sin
 

现在fsin 函数的句柄。就像(在现实生活中)门把手是一种使用门的方式一样,功能手柄是一种使用功能的方式。要使用f ,将参数传递给它,就像它是sin 函数一样:

>> f(pi/2)
ans =
     1
 

f 接受sin 函数接受的任何输入参数。如果sin 是一个接受零输入参数的函数(它没有,但是其他参数,例如peaks 函数), f() 将用于在没有输入参数的情况下调用它。

自定义匿名功能

一个变量的匿名函数

创建现有函数的句柄显然没有用,例如上面示例中的sin 。在这个例子中它是多余的。但是,创建匿名函数非常有用,这些函数可以执行自定义操作,否则需要多次重复或创建单独的函数。作为自定义匿名函数的一个示例,它接受一个变量作为其输入,求和信号的正弦和余弦平方:

>> f = @(x) sin(x)+cos(x).^2
f = 
    @(x)sin(x)+cos(x).^2
 

现在f 接受一个名为x 输入参数。这是在@ 运算符后直接使用括号(...) 指定的。 f now是xf(x) 的匿名函数。通过将值x 传递给f 来使用它:

>> f(pi)
ans =
    1.0000
 

值或变量的向量也可以传递给f ,只要它们在f 中以有效的方式使用:

>> f(1:3) % pass a vector to f
ans =
    1.1334    1.0825    1.1212
>> n = 5:7;
>> f(n) % pass n to f
ans =
   -0.8785    0.6425    1.2254
 

多个变量的匿名函数

以同样的方式,可以创建匿名函数以接受多个变量。一个接受三个变量的匿名函数示例:

>> f = @(x,y,z) x.^2 + y.^2 - z.^2
f = 
    @(x,y,z)x.^2+y.^2-z.^2
>> f(2,3,4)
ans =
    -3
 

参数化匿名函数

工作空间中的变量可以在匿名函数的定义中使用。这称为参数化。例如,要在匿名函数中使用常量c = 2

>> c = 2;
>> f = @(x) c*x
f = 
    @(x)c*x
>> f(3)
ans =
     6
 

f(3) 使用变量c 作为参数与所提供的x 相乘。请注意,如果此时c 的值设置为不同的值,则调用f(3) ,结果不会有所不同。 c 的值是创建匿名函数时的值:

>> c = 2;
>> f = @(x) c*x;
>> f(3)
ans =
     6
>> c = 3;
>> f(3)
ans =
     6
 

匿名函数的输入参数不引用工作空间变量

请注意,使用工作空间中的变量名称作为匿名函数的输入参数之一(即使用@(...) )将不会使用这些变量的值。相反,它们被视为匿名函数范围内的不同变量,即:匿名函数具有其私有工作空间,其中输入变量从不引用主工作空间中的变量。主工作区和匿名函数的工作区不了解彼此的内容。举例说明:

>> x = 3 % x in main workspace
x =
     3
>> f = @(x) x+1; % here x refers to a private x variable
>> f(5)
ans =
     6
>> x
x =
     3
 

f 不使用主工作空间中的x 值。此外,在主工作区中, x 保持不变。在f 的范围内, @ 运算符后括号内的变量名与主工作空间变量无关。

匿名函数存储在变量中

匿名函数(或者更确切地说,指向匿名函数的函数句柄)与当前工作空间中的任何其他值一样存储:在变量中(如上所述),在单元格数组中( {@(x)x.^2,@(x)x+1} ),甚至是属性(如交互式图形的h.ButtonDownFcn )。这意味着匿名函数可以像任何其他值一样对待。将其存储在变量中时,它在当前工作空间中具有名称,并且可以像保存数字的变量一样进行更改和清除。

换句话说:函数句柄(无论是@sin 形式还是匿名函数)只是一个可以存储在变量中的值,就像数值矩阵一样。

高级用途

将函数句柄传递给其他函数

由于函数句柄被视为变量,因此它们可以传递给接受函数句柄作为输入参数的函数。

示例:在m文件中创建一个函数,该文件接受函数句柄和标量数。然后通过向它传递3 来调用函数句柄,然后将标量数添加到结果中。结果返回。

funHandleDemo.m 内容:

function y = funHandleDemo(fun,x)
y = fun(3);
y = y + x;
 

将它保存在路径上的某个位置,例如在MATLAB的当前文件夹中。现在funHandleDemo 可以如下使用,例如:

>> f = @(x) x^2; % an anonymous function
>> y = funHandleDemo(f,10) % pass f and a scalar to funHandleDemo
y =
    19
 

另一个现有函数的句柄可以传递给funHandleDemo

>> y = funHandleDemo(@sin,-5)
y =
   -4.8589
 

注意@sin 如何快速访问sin 函数,而不首先使用f = @sin 将其存储在变量中。

使用bsxfuncellfun 和类似函数与匿名函数

MATLAB有一些内置函数可以接受匿名函数作为输入。这是一种用最少的代码行执行许多计算的方法。例如,执行逐元素二元运算的bsxfun ,即:它以逐元素的方式在两个向量或矩阵上应用函数。通常,这将需要使用for -loops,这通常需要预先分配速度。使用bsxfun 加快了这个过程。以下示例使用tictoc 说明了这一点,这两个函数可用于计算代码所需的时间。它计算矩阵列均值中每个矩阵元素的差异。

A = rand(50); % 50-by-50 matrix of random values between 0 and 1

% method 1: slow and lots of lines of code
tic
meanA = mean(A); % mean of every matrix column: a row vector
% pre-allocate result for speed, remove this for even worse performance
result = zeros(size(A));
for j = 1:size(A,1)
    result(j,:) = A(j,:) - meanA;
end
toc
clear result % make sure method 2 creates its own result

% method 2: fast and only one line of code
tic
result = bsxfun(@minus,A,mean(A));
toc
 

运行上面的示例会产生两个输出:

Elapsed time is 0.015153 seconds.
Elapsed time is 0.007884 seconds.
 

这些行来自toc 函数,它们打印自上次调用tic 函数以来经过的时间。

bsxfun 调用将第一个输入参数中的函数应用于其他两个输入参数。 @minus 是与减号相同的操作的长名称。可以指定与任何其他函数不同的匿名函数或句柄( @ ),只要它接受Amean(A) 作为输入即可生成有意义的结果。

特别是对于大型矩阵中的大量数据, bsxfun 可以加速很多事情。它还使代码看起来更清晰,尽管对于不了解MATLAB或bsxfun 人来说可能更难解释。 (请注意,在MATLAB R2016a及更高版本中,以前使用bsxfun 许多操作不再需要它们; A-mean(A) 直接工作,在某些情况下可能更快。)

细胞阵列

同一个类的元素通常可以连接成数组(有一些罕见的例外,例如函数句柄)。默认为double 类的数字标量可以存储在矩阵中。

>> A = [1, -2, 3.14, 4/5, 5^6; pi, inf, 7/0, nan, log(0)]
A =
   1.0e+04 *
    0.0001   -0.0002    0.0003    0.0001    1.5625
    0.0003       Inf       Inf       NaN      -Inf
 

在MATLAB中属于char 类的char 也可以使用类似的语法存储在数组中。这样的数组类似于许多其他编程语言中的字符串。

>> s = ['MATLAB ','is ','fun']
s =
MATLAB is fun
 

请注意,尽管它们都使用括号[] ,但结果类是不同的。因此,可以对它们进行的操作也是不同的。

>> whos
  Name      Size            Bytes  Class     Attributes

  A         2x5                80  double              
  s         1x13               26  char                
 

实际上,数组s 不是字符串'MATLAB ''is ''fun' 的数组,它只是一个字符串 - 一个包含13个字符的数组。如果由以下任何一项定义,您将得到相同的结果:

>> s = ['MAT','LAB ','is f','u','n'];
>> s = ['M','A','T','L','A','B,' ','i','s',' ','f','u','n'];
 

常规的MATLAB向量不允许存储不同类或几个不同字符串的变量混合。这是cell 阵列派上用场的地方。这是一个单元格数组,每个单元格都可以包含一些MATLAB对象,如果需要,它们的类在每个单元格中都可以不同。在元素周围使用花括号{} 来存储在单元格数组中。

>> C = {A; s}
C = 
    [2x5 double]
    'MATLAB is fun'
>> whos C
  Name      Size            Bytes  Class    Attributes

  C         2x1               330  cell 
 

任何类的标准MATLAB对象可以一起存储在单元阵列中。请注意,单元阵列需要更多内存来存储其内容。

使用花括号{} 来访问单元格的内容。

>> C{1}
ans =
   1.0e+04 *
    0.0001   -0.0002    0.0003    0.0001    1.5625
    0.0003       Inf       Inf       NaN      -Inf
 

注意, C(1) 不同于C{1} 。虽然后者返回单元格的内容(并且在示例中具有类double ),但前者返回一个单元格数组,该数组是C 的子数组。类似地,如果D 是10乘5的单元阵列,则D(4:8,1:3) 将返回D 的子阵列,其大小为5乘3并且其类是cell 。语法C{1:2} 没有单个返回的对象,但是rater返回2个不同的对象(类似于具有多个返回值的MATLAB函数):

>> [x,y] = C{1:2}
x =
                         1                        -2                      3.14                       0.8                     15625
          3.14159265358979                       Inf                       Inf                       NaN                      -Inf
y =
MATLAB is fun
 

数据类型

MATLAB中有16种基本数据类型或类。这些类中的每一个都是矩阵或数组的形式。除了函数句柄之外,这个矩阵或数组的大小至少为0乘0,并且可以增长到任何大小的n维数组。函数句柄始终是标量(1乘1)。

MATLAB中的重要时刻是默认情况下不需要使用任何类型声明或维度语句。定义新变量时,MATLAB会自动创建它并分配适当的内存空间。

例:

a = 123;
b = [1 2 3];
c = '123';

>> whos
  Name      Size            Bytes  Class     Attributes

  a         1x1                 8  double              
  b         1x3                24  double              
  c         1x3                 6  char    
 

如果变量已经存在,MATLAB将用新的数据替换原始数据,并在必要时分配新的存储空间。

基本数据类型

基本数据类型包括:numeric, logicalcharcellstructtablefunction_handle

数字数据类型

  • 浮点数默认

    MATLAB以双精度或单精度格式表示浮点数。默认值是双精度,但您可以使用简单的转换函数使任何数字单精度:

    a = 1.23;
    b = single(a);
    
    >> whos
      Name      Size            Bytes  Class     Attributes
    
      a         1x1                 8  double              
      b         1x1                 4  single     
     
  • 整型

    MATLAB有四个有符号整数和四个无符号整数类。有符号类型使您可以使用负整数和正整数,但不能表示与无符号类型一样宽的数字范围,因为一位用于指定数字的正号或负号。无符号类型为您提供更广泛的数字,但这些数字只能为零或正数。

    MATLAB支持整数数据的1位,2位,4位和8字节存储。如果使用适合数据的最小整数类型,则可以节省程序的内存和执行时间。例如,您不需要32位整数来存储值100。

    a = int32(100);
    b = int8(100);
    
    >> whos
      Name      Size            Bytes  Class    Attributes
    
      a         1x1                 4  int32              
      b         1x1                 1  int8               
     

    要将数据存储为整数,您需要将double转换为所需的整数类型。如果转换为整数的数字具有小数部分,则MATLAB将舍入为最接近的整数。如果小数部分恰好是0.5 ,那么从两个接近的整数中,MATLAB选择绝对值大小的那个。

    a  = int16(456);
     
  • char

    字符数组为MATLAB中的文本数据提供存储。与传统的编程术语保持一致,字符的数组(序列)被定义为字符串。 MATLAB的零售版中没有明确的字符串类型。

  • logical:逻辑值为1或0,分别表示true和false。用于关系条件和数组索引。因为它只是TRUE或FALSE,所以它的大小为1个字节。

    a = logical(1);
     
  • 结构体。结构数组是一种数据类型,它使用称为字段的数据容器对不同数据类型的变量进行分组。每个字段可以包含任何类型的数据。使用structName.fieldName形式的点表示法访问结构中的数据。

    field1 = 'first';
    field2 = 'second';
    value1 = [1 2 3 4 5];
    value2 = 'sometext';
    s = struct(field1,value1,field2,value2);
     

    为了访问value1,以下每个语法都是等效的

    s.first or s.(field1) or s.('first')
     

    我们可以使用第一种方法显式访问我们知道将存在的字段,或者传递字符串或创建字符串以访问第二个示例中的字段。第三个例子是说明点父语法符号采用一个字符串,该字符串与存储在field1变量中的字符串相同。

  • 表变量可以具有不同的大小和数据类型,但所有变量必须具有相同的行数。

    Age = [15 25 54]';
    Height = [176 190 165]';
    Name = {'Mike', 'Pete', 'Steeve'}';
    T = table(Name,Age, Height);
     
  • 细胞。它是非常有用的MATLAB数据类型:单元阵列是一个数组,它的每个元素可以是不同的数据类型和大小。它是非常强大的工具,可以根据需要操作数据。

    a = { [1 2 3], 56, 'art'};
     

    要么

    a = cell(3);
     
  • function handle存储指向函数的指针(例如,存储到匿名函数)。它允许您将函数传递给另一个函数,或从main函数外部调用本地函数。

每种数据类型都有很多工具,还有内置的数据类型转换函数str2doubletable2cell )。

其他数据类型

有几种其他数据类型在某些特定情况下很有用。他们是:

  • 日期和时间:表示日期,时间和持续时间的数组。 datetime('now') 返回21-Jul-2016 16:30:16

  • 分类数组:它是用于存储具有一组离散类别的值的数据的数据类型。用于存储非数字数据(存储器有效)。可以在表中使用来选择行组。

    a = categorical({'a' 'b' 'c'});
     
  • 映射容器是一种数据结构,它具有独特的能力,不仅可以通过任何标量数值而且可以通过字符向量进行索引。对Map元素的索引称为键。这些键以及与它们关联的数据值存储在Map中。

  • 时间序列是按时间顺序采样的数据向量,通常以规则的间隔进行。存储与时间步长相关的数据非常有用,它有许多有用的方法可供使用。

你好,世界

在MATLAB编辑器中打开一个新的空白文档(在最近的MATLAB版本中,通过选择工具条的“主页”选项卡,然后单击“新建脚本”来完成此操作)。创建新脚本的默认键盘快捷键是Ctrl-n

或者,键入edit myscriptname.m 将打开文件myscriptname.m 进行编辑,或者如果在MATLAB路径中不存在则提供创建文件。

在编辑器中,键入以下内容:

disp('Hello, World!');
 

选择工具条的“编辑器”选项卡,然后单击“另存为”。将文档保存到当前名为helloworld.m 目录中的文件中。保存无标题文件将弹出一个对话框来命名文件。

在MATLAB命令窗口中,键入以下内容:

>> helloworld
 

您应该在MATLAB命令窗口中看到以下响应:

Hello, World!
 

我们看到,在命令窗口中,我们可以键入我们编写的函数或脚本文件的名称,或者运行它们的MATLAB附带的脚本文件的名称。

在这里,我们运行了'helloworld'脚本。请注意,输入扩展名( .m )是不必要的。脚本文件中的指令由MATLAB执行,这里打印'Hello,World!'使用disp 函数。

脚本文件可以用这种方式编写,以保存一系列命令供以后(重新)使用。

帮助自己

MATLAB附带了许多内置脚本和函数,范围从简单的乘法到图像识别工具箱。要获取有关要使用的help functionname ,请在命令行中键入help functionname 。让我们以help 功能为例。

可以通过键入以下内容获取有关如何使用它的信息:

>> help help

在命令窗口中。这将返回功能help 的使用信息。如果您要查找的信息仍不清楚,可以尝试该功能的文档页面。只需输入:

>> doc help

在命令窗口中。这将打开页面上可浏览的文档,以获取功能help 提供了解“帮助”工作原理所需的所有信息。

此过程适用于所有内置函数和符号。

在开发自己的函数时,可以通过在函数文件顶部添加注释或在函数声明之后添加注释来让他们拥有自己的帮助部分。

保存在文件multiplyby2.m 的简单函数multiplyby2 示例

function [prod]=multiplyby2(num)
% function MULTIPLYBY2 accepts a numeric matrix NUM and returns output PROD 
% such that all numbers are multiplied by 2

    prod=num*2;
end
 

要么

% function MULTIPLYBY2 accepts a numeric matrix NUM and returns output PROD 
% such that all numbers are multiplied by 2

function [prod]=multiplyby2(num)
    prod=num*2;
end
 

在您编写代码后的几周/几个月/几年内获取代码时,这非常有用。

helpdoc 函数提供了大量信息,学习如何使用这些功能将帮助您快速进步并有效地使用MATLAB。

索引矩阵和数组

MATLAB允许多种方法来索引(访问)矩阵和数组的元素:

  • 下标索引 - 您可以分别在矩阵的每个维度中指定所需元素的位置。
  • 线性索引 - 矩阵被视为向量,无论其大小如何。这意味着,您可以使用单个数字指定矩阵中的每个位置。
  • 逻辑索引 - 您使用逻辑矩阵(以及true 值和false 值的矩阵),其中您尝试将矩阵的相同维度作为掩码进行索引,以指定要返回的值。

现在使用以下3乘3矩阵M 作为示例更详细地解释这三种方法:

>> M = magic(3)

ans = 

       8    1    6
       3    5    7
       4    9    2
 

下标索引

访问元素最直接的方法是指定其行列索引。例如,访问第二行和第三列上的元素:

>> M(2, 3)

ans =

      7
 

提供的下标数量与M 具有的维度数量完全匹配(本例中为两个)。

请注意,下标的顺序与数学约定相同:行索引是第一个。此外, 大多数编程语言一样,MATLAB索引1 开始不是0

您可以通过为每个坐标传递矢量而不是单个数字来一次索引多个元素。例如,为了获得整个第二行,我们可以指定我们想要第一,第二和第三列:

>> M(2, [1,2,3])

ans =

       3    5    7
 

在MATLAB中,使用冒号运算符(即1:3 )更容易创建向量[1,2,3] 。您也可以在索引中使用它。为了选择整行(或列),MATLAB提供了一个快捷方式,允许您指定: 。例如,以下代码也将返回整个第二行

>> M(2, :)

ans =

       3    5    7
 

MATLAB还提供了一个快捷方式,用于以end 关键字的形式指定维度的最后一个元素。 end 关键字的工作方式与该维度中最后一个元素的编号完全相同。因此,如果您希望第2 列中的所有列到最后一列,则可以使用以下内容编写:

>> M(2, 2:end)

ans =

       5    7
 

下标索引可能是限制性的,因为它不允许从不同的列和行中提取单个值;它将提取所有行和列的组合。

>> M([2,3], [1,3])
ans =

       3    7
       4    2
 

例如,下标索引不能仅提取元素M(2,1)M(3,3) 。为此,我们必须考虑线性索引。

线性索引

当您仅使用一个维度进行索引时,MATLAB允许您将n维数组视为一维数组。您可以直接访问第一个元素:

>> M(1)

ans = 

       8
 

请注意,数组在MATLAB中以列主顺序存储,这意味着您可以通过首先向下列来访问元素。所以M(2) 是第一列的第二个元素是3M(4) 将是第二列的第一个元素,即

>> M(4)

ans = 

        1
 

在MATLAB中存在内置函数将下标索引转换为线性索引,反之亦然: sub2ind ind2sub 分别。您可以手动将下标( rc )转换为线性索引

idx = r + (c-1)*size(M,1)
 

要理解这一点,如果我们在第一列,那么线性索引将只是行索引。上面的公式适用于此,因为对于c == 1(c-1) == 0 。在下一列中,线性索引是行号加上前一列的所有行。

请注意, end 关键字仍然适用,现在引用数组的最后一个元素,即M(end) == M(end, end) == 2

您还可以使用线性索引来索引多个元素。请注意,如果这样做,返回的矩阵将具有与索引向量矩阵相同的形状。

M(2:4) 返回行向量,因为2:4 表示行向量[2,3,4]

>> M(2:4)

ans =

        3    4    1
 

作为另一个例子, M([1,2;3,4]) 返回2乘2的矩阵,因为[1,2;3,4] 也是2乘2的矩阵。请参阅以下代码以说服自己:

>> M([1,2;3,4])

ans =

       8        3
       4        1
 

请注意,使用: alone进行索引将始终返回列向量:

>> M(:)

ans = 

        8
        3
        4
        1
        5
        9
        6
        7
        2
 

此示例还说明了MATLAB在使用线性索引时返回元素的顺序。

逻辑索引

第三种索引方法是使用逻辑矩阵(即仅包含truefalse 值的矩阵)作为掩码来过滤掉您不想要的元素。例如,如果我们想要找到大于5M 所有元素,我们可以使用逻辑矩阵

>> M > 5

ans =

    1    0    1
    0    0    1
    0    1    0
 

索引M 并仅返回大于5 的值,如下所示:

>> M(M > 5)

ans =

        8
        9
        6
        7
 

如果你想让这些数字保持原位(即保持矩阵的形状),那么你可以分配给逻辑恭维

>> M(~(M > 5)) = NaN

ans = 

    8      NaN    6
    NaN    NaN    7
    NaN    9      Nan
 

我们可以通过使用逻辑索引来减少包含iffor 语句的复杂代码块。

采用非向量化(通过使用线性索引已经缩短为单个循环):

for elem = 1:numel(M)
  if M(elem) > 5
    M(elem) = M(elem) - 2;
  end
end
 

这可以使用逻辑索引缩短为以下代码:

idx = M > 5;
M(idx) = M(idx) - 2;
 

甚至更短:

M(M > 5) = M(M > 5) - 2;
 

更多关于索引

更高维矩阵

上面提到的所有方法都归纳为n维。如果我们使用三维矩阵M3 = rand(3,3,3) 作为示例,那么您可以通过写入访问第三维的第二个切片的所有行和列

>> M(:,:,2)
 

您可以使用线性索引访问第二个切片的第一个元素。线性索引仅在第一个切片的所有行和所有列之后移动到第二个切片。所以该元素的线性索引是

>> M(size(M,1)*size(M,2)+1)
 

实际上,在MATLAB中, 每个矩阵都是n维的:恰好是大多数其他n维的大小都是1。所以,如果a = 2a(1) == 2 (正如人们所期望的那样), 而且 a(1, 1) == 2 a(1, 1, 1) == 2a(1, 1, 1, ..., 1) == 2 a(1, 1, 1) == 2a(1, 1, 1, ..., 1) == 2 等等。这些“额外”尺寸(尺寸1 )被称为单体尺寸 。命令squeeze 将删除它们,并且可以使用permute 来交换维度的顺序(如果需要,引入单例维度)。

还可以使用m个下标(其中m <= n)来索引n维矩阵。规则是第一个m-1下标通常表现,而最后一个(第m个)下标引用剩余的(n-m + 1)维度,就像线性索引引用(n-m + 1)维一样阵列。这是一个例子:

>> M = reshape(1:24,[2,3,4]);
>> M(1,1)
ans =
     1
>> M(1,10)
ans =
    19
>> M(:,:)
ans =
     1     3     5     7     9    11    13    15    17    19    21    23
     2     4     6     8    10    12    14    16    18    20    22    24
 

返回元素范围

使用下标索引,如果在多个维度中指定多个元素,MATLAB将返回每对可能的坐标。例如,如果你尝试M([1,2],[1,3]),MATLAB将返回M(1,1)M(2,3) 但它将返回M(1,3)M(2,1) 。这可以当你正在寻找坐标对,但考虑更大的矩阵的例子中的一个列表中的元素似乎并不直观A = rand(20) 注意: A 是现在20 -by- 20 ),在那里你想要得到的右上象限。在这种情况下,您不必指定该象限中的每个坐标对(这种情况下将是100 对),您只需指定10 行和10 列,即A(1:10, 11:end) 。像这样切割矩阵比需要坐标对列表更常见。

如果您确实想要获得坐标对列表,最简单的解决方案是转换为线性索引。考虑一个问题,其中有一个要返回的列索引向量,其中向量的每一行包含要为矩阵的相应行返回的列号。例如

colIdx = [3;2;1]
 

所以在这种情况下,你实际上想要回到(1,3)(2,2)(3,1) 处的元素。所以使用线性索引:

>> colIdx = [3;2;1];
>> rowIdx = 1:length(colIdx);
>> idx = sub2ind(size(M), rowIdx, colIdx);
>> M(idx)

ans = 

        6    5    4
 

多次返回元素

使用下标和线性索引,您还可以通过重复索引来多次返回元素

>> M([1,1,1,2,2,2])

ans = 

        8    8    8    3    3    3
 

您可以使用它来复制整个行和列,例如重复第一行和最后一列

>> M([1, 1:end], [1:end, end])

ans = 

        8    1    6    6 
        8    1    6    6
        3    5    7    7
        4    9    2    2
 

有关更多信息,请参阅此处

矩阵和数组

在MATLAB中,最基本的数据类型是数字数组。它可以是标量,1-D向量,2-D矩阵或ND多维数组。

% a 1-by-1 scalar value
x = 1;
 

要创建行向量,请在括号内输入元素,用空格或逗号分隔:

% a 1-by-4 row vector
v = [1, 2, 3, 4];
v = [1 2 3 4];
 

要创建列向量,请使用分号分隔元素:

% a 4-by-1 column vector
v = [1; 2; 3; 4];
 

要创建矩阵,我们输入以前用分号分隔的行:

% a 2 row-by-4 column matrix
M = [1 2 3 4; 5 6 7 8];

% a 4 row-by-2 column matrix
M = [1 2; ...
     4 5; ...
     6 7; ...
     8 9];
 

请注意,您无法创建行/列大小不相等的矩阵。所有行的长度必须相同,并且所有列的长度必须相同:

% an unequal row / column matrix
M = [1 2 3 ; 4 5 6 7]; % This is not valid and will return an error

% another unequal row / column matrix
M = [1 2 3; ...
     4   5; ...
     6 7 8; ...
     9   10];     % This is not valid and will return an error
 

为了转置矢量或矩阵,我们使用.' ' 操作者,或' 运算符来取其Hermitian共轭,这是它的转置的复共轭。对于真实矩阵,这两个是相同的:

% create a row vector and transpose it into a column vector
v = [1 2 3 4].';              % v is equal to [1; 2; 3; 4];

% create a 2-by-4 matrix and transpose it to get a 4-by-2 matrix
M = [1 2 3 4; 5 6 7 8].';     % M is equal to [1 5; 2 6; 3 7; 4 8]

% transpose a vector or matrix stored as a variable
A = [1 2; 3 4];
B = A.';                      % B is equal to [1 3; 2 4]
 

对于超过二维的数组,没有直接的语言语法可以直接输入它们。相反,我们必须使用函数来构造它们(如oneszerosrand )或通过操纵其他阵列(使用功能,如catreshapepermute )。一些例子:

% a 5-by-2-by-4-by-3 array (4-dimensions)
arr = ones(5, 2, 4, 3);

% a 2-by-3-by-2 array (3-dimensions)
arr = cat(3, [1 2 3; 4 5 6], [7 8 9; 0 1 2]);

% a 5-by-4-by-3-by-2 (4-dimensions)
arr = reshape(1:120, [5 4 3 2]);
 

读取输入和写入输出

就像所有编程语言一样,Matlab设计用于以各种格式进行读写。本机库支持大量的文本,图像,视频,音频,数据格式,每种版本更新中包含更多格式 - 请在此处查看支持的文件格式的完整列表以及用于导入它们的功能。

在尝试加载文件之前,您必须问自己,您希望数据成为什么样,以及您希望计算机如何为您组织数据。假设您有以下格式的txt / csv文件:

Fruit,TotalUnits,UnitsLeftAfterSale,SellingPricePerUnit
Apples,200,67,$0.14
Bananas,300,172,$0.11
Pineapple,50,12,$1.74
 

我们可以看到第一列是字符串格式,第二列是数字,最后一列是货币形式。假设我们想要找到今天使用Matlab赚取多少收入,首先我们要加载这个txt / csv文件。检查链接后,我们可以看到textscan 处理字符串和数字类型的txt文件。所以我们可以尝试:

fileID = fopen('dir/test.txt'); %Load file from dir
C = textscan(fileID,'%s %f %f %s','Delimiter',',','HeaderLines',1); %Parse in the txt/csv
 

其中%s 表示该元素是String类型, %f 表示该元素是Float类型,并且该文件由“,”分隔。 HeaderLines选项要求Matlab跳过前N行,而紧跟在后面的1表示跳过第一行(标题行)。

现在C是我们加载的数据,其形式为4个单元格的单元格,每个单元格包含txt / csv文件中的数据列。

首先,我们想要通过从第二列中减去第三列来计算我们今天销售的水果数量,这可以通过以下方式完成:

sold = C{2} - C{3}; %C{2} gives the elements inside the second cell (or the second column)
 

现在我们想要将此向量乘以每单位价格,所以首先我们需要将字符串转换为一列数字,然后使用Matlab的cell2mat 将其转换为数字矩阵,我们首先需要做的是cell2mat 关闭“$”符号,有很多方法可以做到这一点。最直接的方法是使用简单的正则表达式:

D = cellfun(@(x)(str2num(regexprep(x, '\$',''))), C{4}, 'UniformOutput', false);%cellfun allows us to avoid looping through each element in the cell.
 

或者你可以使用循环:

for t=1:size(C{4},1)
   D{t} = str2num(regexprep(C{4}{t}, '\$',''));
end

E = cell2mat(D)% converts the cell array into a Matrix
 

str2num 函数将str2num “$”符号的字符串转换为数字类型,而cell2mat 将数字元素的单元格转换为数字矩阵

现在我们可以将销售的单位乘以每单位成本:

revenue = sold .* E; %element-wise product is denoted by .* in Matlab

totalrevenue = sum(revenue);
 

脚本和函数

MATLAB代码可以保存在m文件中以便重用。 m文件具有.m 扩展名,它与MATLAB自动关联。 m文件可以包含脚本或函数。

脚本

脚本只是程序文件,它以预定义的顺序执行一系列MATLAB命令。

脚本不接受输入,脚本也不返回输出。从功能上讲,脚本相当于直接在MATLAB命令窗口中输入命令并能够重放它们。

脚本的一个例子:

length = 10;
width = 3;
area = length * width;
 

该脚本将确定lengthwidth ,和area 在当前工作空间中具有值103 ,和30 分别。

如前所述,上述脚本在功能上等同于直接在命令窗口中键入相同的命令。

>> length = 10;
>> width = 3;
>> area = length * width;
 

功能

与脚本相比,函数更加灵活和可扩展。与脚本不同,函数可以接受输入并将输出返回给调用者。函数具有自己的工作空间,这意味着函数的内部操作不会更改调用者的变量。

所有函数都使用相同的标头格式定义:

function [output] = myFunctionName(input)
 

function 关键字开始每个函数头。产出清单如下。输出列表也可以是要返回的逗号分隔的变量列表。

function [a, b, c] = myFunctionName(input)
 

接下来是将用于调用的函数的名称。这通常与文件名相同。例如,我们将此函数保存为myFunctionName.m

函数名称后面是输入列表。与输出一样,这也可以是逗号分隔列表。

function [a, b, c] = myFunctionName(x, y, z)
 

我们可以将之前的示例脚本重写为可重用的函数,如下所示:

function [area] = calcRecArea(length, width)
   area = length * width;
end
 

我们可以从其他函数调用函数,甚至可以从脚本文件调用函数。以下是我们在脚本文件中使用的上述函数的示例。

l = 100;
w = 20;
a = calcRecArea(l, w);
 

和以前一样,我们创建lw ,和a 在与的值在工作区10020 ,和2000 分别。