跳转至

数据类型简介

在 MATLAB 中,最基本的数据结构是 数组 (Array)。可以说,MATLAB 的核心设计哲学就是“一切皆为数组”。无论是单个数值、一段文本、还是复杂的数据集合,其底层都以多维数组的形式存在。本篇文档将从这一核心概念出发,详细介绍 MATLAB 中的各类数据。

动态类型语言

MATLAB 是一种动态类型语言,这意味着您通常无需在创建变量时显式声明其数据类型。MATLAB 会根据您赋给变量的值自动选择最合适的类型。例如,执行 x = 10 会自动创建一个 \(1 \times 1\)double 类型数组。

MATLAB 数组:核心基石

一个 MATLAB 数组是一个由多个元素组成的集合,这些元素被组织在一个 N 维的网格中。

  • 维度 (Dimension): 数组的维度是其最核心的属性。
    • 示例:
      s = 10; % 标量 (1x1 数组)
      v = [1, 2, 3]; % 行向量 (1x3 数组)
      m = [1, 2; 3, 4]; % 矩阵 (2x2 数组)
      n_dim_array = rand(2, 2, 3); % 2x2x3 的三维数组
      
  • 索引 (Indexing):

    • 示例:
      A = [10, 20, 30; 40, 50, 60; 70, 80, 90];
      
      element = A(2, 3);      % 获取第 2 行第 3 列的元素,结果为 60
      row_vec = A(1, :);      % 获取第一整行,结果为 [10, 20, 30]
      col_vec = A(:, end);    % 获取最后一整列,结果为 [30; 60; 90]
      sub_matrix = A(1:2, 2:3); % 获取左上角的 2x2 子矩阵
      
  • 同质性 vs 异构性:

    • 同质数组 (Homogeneous): 数组中所有元素的数据类型完全相同。这是基础数据类型(如数值、逻辑)的特征。
    • 异构数组 (Heterogeneous): 数组中的元素可以有不同的数据类型。这是通过元胞数组和结构体等容器实现的。

基础数据类型 (同质数组)

这些数组的所有元素都必须是同一种数据类型。

数值数组 (Numeric Array)

这是科学计算中最常用的数组类型,其浮点数表示遵循 IEEE 754 标准

  • double (双精度):
    • 示例:
      a = 10.5; % 默认创建为 double
      b = [1.2, 3.4; 5.6, 7.8]; % double 矩阵
      c = 1 + 2i; % 复数,实部和虚部都是 double
      
      % 使用 whos 查看变量信息
      whos a b c
      
  • single (单精度):
    • 示例:
      % 必须使用 single() 函数进行显式转换
      s = single(10.5);
      
      % 创建一个大型单精度随机矩阵以节省内存
      large_single_array = rand(1000, 1000, 'single');
      
      % 比较 double 和 single 的内存占用
      large_double_array = rand(1000, 1000);
      whos large_single_array large_double_array
      
  • 整数 (int*, uint*):
    • 示例:
      % 图像像素通常使用 uint8
      pixel_value = uint8(255);
      
      % 计数器可以使用有符号整数
      event_counter = int32(-10000);
      
      % intmax/intmin 查看整数类型的范围
      min_val = intmin('int16');
      max_val = intmax('int16');
      
      whos pixel_value event_counter
      disp(['int16 的范围是 [', num2str(min_val), ', ', num2str(max_val), ']']);
      

逻辑数组 (Logical Array)

  • 描述: 数组的所有元素都是逻辑值 true (1) 或 false (0)。
  • 示例:
    A = [10, 25, 5, 40, 15];
    
    % 创建一个逻辑掩码 (mask)
    L = A > 20; % L 的值为 [false, true, false, true, false]
    
    % 使用逻辑索引提取所有大于 20 的元素
    elements_greater_than_20 = A(L); % 结果为 [25, 40]
    
    % 一步完成筛选和赋值
    A(A <= 20) = 0; % 将所有不大于 20 的元素替换为 0
    % A 现在是 [0, 25, 0, 40, 0]
    

文本数组 (Text Array)

  • 示例:
    % char 字符数组
    char_array = 'hello'; % 1x5 char
    char_matrix = ['row1'; 'row2']; % 2x4 char
    
    % string 字符串数组
    string_array = "hello";
    string_vector = ["text1", "a much longer text2"];
    
    % 推荐使用 string 进行操作
    new_string = string_array + " world"; % 结果是 "hello world"
    
    whos char_array string_array
    

复合数据类型 (异构容器)

这些类型也是数组,但它们的元素是“容器”,每个容器可以独立地存放不同类型的数据。

元胞数组 (Cell Array)

  • 描述: 一种其元素为“元胞”的数组。每个元胞都可以存放任意类型的数据,如一个 \(N \times M\) 矩阵、一个字符串和一个函数句柄。
  • 示例:
    % 创建一个 1x3 的元胞数组
    C = {[1, 2; 3, 4], "some text", true};
    
    % 使用 {} 访问元胞内部的内容
    matrix_data = C{1}; % 提取第一个元胞的内容,是一个 2x2 矩阵
    text_data = C{2};   % 提取第二个元胞的内容,是一个 string
    
    % 使用 () 访问元胞本身
    sub_cell = C(1:2); % 提取前两个元胞,结果仍是一个 1x2 元胞数组
    
    % 修改元胞内容
    C{3} = 1:10;
    disp(C);
    

结构体数组 (Structure Array)

  • 描述: 一种其元素为“结构体”的数组。每个结构体通过命名的“字段”(Field)来组织数据。一个结构体数组 \(S\) 中的所有元素都必须拥有完全相同的字段名。
  • 示例:
    % 创建一个 1x2 的结构体数组
    students(1).name = "Alice";
    students(1).id = 101;
    students(1).grades = [95, 89, 92];
    
    students(2).name = "Bob";
    students(2).id = 102;
    students(2).grades = [78, 85, 80];
    
    % 访问数据
    bob_name = students(2).name;
    alice_grades = students(1).grades;
    
    % 提取所有学生的 name 字段到一个 string 数组中
    all_names = [students.name];
    
    disp(['第二个学生的名字是: ', bob_name]);
    disp('所有学生的名字:');
    disp(all_names);
    

表格 (Table)

  • 描述: 专为列向数据设计的二维数据容器。每一列是一个变量(通常是同质向量),可以有不同的数据类型。非常适合进行数据清洗、筛选、分组等分析任务。
  • 示例:
    LastName = ["Smith"; "Jones"; "Williams"];
    Age = [38; 39; 40];
    Smoker = [true; false; true];
    Height = [71; 69; 64];
    
    % 创建 table,并指定行名和变量名
    T = table(Age, Smoker, Height, 'RowNames', LastName);
    
    % 访问数据
    age_of_jones = T.Age('Jones'); % 使用行名和变量名访问
    smoker_data = T(T.Smoker == true, :); % 筛选出所有吸烟者的数据
    
    disp('完整的表格:');
    disp(T);
    disp('吸烟者的数据:');
    disp(smoker_data);
    

其他专门类型

函数句柄 (Function Handle)

  • 描述: 使用 @ 符号创建,它是一种特殊的数据类型,用于表示一个函数 \(f(x)\) 的引用或“指针”。
  • 示例:
    % 创建一个代表函数 f(x) = x^2 的句柄
    f_square = @(x) x.^2;
    
    % 使用句柄调用函数
    result1 = f_square(5); % 结果是 25
    
    % 将匿名函数句柄直接传递给其他函数
    % 计算定积分 ∫(x*cos(x)) dx from 0 to pi
    result2 = integral(@(x) x.*cos(x), 0, pi);
    
    disp(['f_square(5) 的结果是: ', num2str(result1)]);
    disp(['积分结果是: ', num2str(result2)]);
    

专业类型

  • 示例:
    % categorical 数组
    sizes = ["medium"; "large"; "small"; "medium"];
    cat_sizes = categorical(sizes);
    
    % datetime 数组
    t1 = datetime('now');
    t2 = datetime(2025, 1, 1);
    time_diff = t2 - t1;
    
    disp('分类数组的类别:');
    disp(categories(cat_sizes));
    disp(['距离 2025 年元旦还有: ', char(time_diff)]);
    

常用类型检查函数

  • 示例:
    my_var = {1, 'text', true};
    
    % 使用 class
    disp(['my_var 的类型是: ', class(my_var)]); % 输出 'cell'
    
    % 使用 isa
    is_it_a_cell = isa(my_var, 'cell'); % 结果是 true
    is_it_a_struct = isa(my_var, 'struct'); % 结果是 false
    
    % 使用 whos (在命令行中效果最佳)
    A = rand(10);
    B = "hello";
    whos A B my_var