发表于

MATLAB入门教程:面向C++/OIer的数据可视化与科学计算指南

你好,C++ Coder / OIer!

你习惯于 main 函数、std::vector#include,以及对性能和内存的极致追求。现在,你遇到了一位新工具:MATLAB。将它视为一个面向科学计算和 数据可视化 的交互式环境与计算工作台即可。这篇 MATLAB入门教程 将结合 C++ 的思维模式,帮助你尽快理解 MATLAB 的核心用法。与编译型工作流不同,它更适合交互式探索与计算。

MATLAB集成开发环境界面截图

第一章:环境与心智模型切换 (From IDE to Interactive Shell)

C++ Coder D-e-v's Note: 把 MATLAB IDE 想象成一个自带 REPL (Read-Eval-Print Loop) 的环境。命令窗口 就是你的 stdin/stdout工作区 (Workspace) 则是全局变量的实时监视器。这里的编程更像是写 Python 脚本,而非编译 C++ 项目。

**1. 环境管理:告别 **system("cls")

MATLAB 命令功能描述对标 C++ 概念
clc清空命令窗口显示相当于 system("cls") 或重启控制台,界面清爽,不影响任何变量。
clear清空工作区(变量)类似程序重启,销毁所有全局变量clear x; 则像 delete 单个指针。
who / whos查看工作区变量变量监视窗口的文本版。whossizeoftypeid 的组合体。
cd切换工作目录chdir(),确保你的 .m 文件和数据在当前路径,否则就是 "File Not Found"。

2. 变量:动态类型的世界

C++ Coder D-e-v's Note: MATLAB 是动态强类型语言。你无需声明类型(int a; double b;),解释器会自动推断。但一旦类型确定,运算必须合法。

  • 命名规则:和 C++ 类似,字母开头,可含数字、下划线。

  • 最大陷阱禁止覆盖内置函数! 如果你写 sum = 10;,就相当于你 #define sum 10std::accumulate 瞬间报废。这是 C++ 程序员最常犯的错误。我曾经因为这个坑排查了半天bug,才发现是自己无意中覆盖了内置函数。

3. 数据类型:从底层到应用

% 1. 数值型(默认double) - C++的 double,但也是所有计算的核心
a = 3.14;                 % scalar
b = [1, 2+3i];            % complex vector,原生支持复数,i/j 就像 <complex>

% 2. 逻辑型(logical) - C++的 bool
c = true;                 % 1
d = (5 > 3);              % 关系运算返回 logical 1

% 3. 字符与字符串(char vs. string) - 从 C-style 到 std::string
e = 'Hello';              % char 数组 (单引号),类似 const char*
f = "World";              % string 对象 (双引号),类似 std::string,支持 `+` 拼接

第二章:核心武器库 —— 矩阵与向量化运算

C++ Coder D-e-v's Note: 这是 MATLAB 的核心特征,也是与 C++ 思维的主要差异。在 C++ 中,你用 for 循环遍历数组;在 MATLAB 中,你对整个数组直接进行数学运算。这个叫向量化 (Vectorization)

1. 数组创建与索引:std::vector 的超集

**注意:**MATLAB 索引从 1 开始,arr[0] 会报错。

% --- 创建 ---
% 行向量 (1xN 矩阵)
row_vec = [1 2 3 4];      % 类似 std::vector<int> v = {1, 2, 3, 4};

% 列向量 (Nx1 矩阵)
col_vec = [5; 6; 7];      % 分号换行
col_vec2 = row_vec';    % ' (单引号) 是转置,高效常用

% 二维矩阵
matrix = [1 2 3; 4 5 6]; % 类似 vector<vector<int>> m = {{1,2,3}, {4,5,6}};

% --- 索引与切片 ---
A = [1 2 3; 4 5 6; 7 8 9];
A(2,3)                  % 第2行第3列 -> 6 (不是 A[1][2]!)
A(:, 2)                 % C++ 中较少见的操作:取第2列所有元素 (冒号 : 代表'全部')
A(1:2, end)             % 取1到2行,最后一列 ('end' 关键字,类似 v.size()-1)
A(A > 5)                % 逻辑索引,返回一个扁平化的向量,包含所有 >5 的元素

2. 矩阵运算 (*) vs. 元素级运算 (.*):代数与数据的分界

这是 MATLAB 的核心精髓。理解了它,你就超越了 90% 的新手。

  • 矩阵运算 (*, /, ^)** -> 线性代数模式,遵循数学定义,需要维度匹配(A(m×n) * B(n×p))。这就是你手算矩阵乘法的那个规则。
  • 元素级运算 (.*, ./, .^)** -> 数据处理模式 (C++ for 循环的替代品)。操作符前的 . 告诉 MATLAB:“别管什么线性代数,把这两个同样大小的矩阵对应位置的元素拿出来做运算!”
A = [1 2; 3 4]; B = [5 6; 7 8];

% 矩阵乘法 => A * B,手算结果
C_matrix_mul = A * B;       % -> [19 22; 43 50]

% 元素级乘法 => for(i) for(j) C[i][j] = A[i][j] * B[i][j];
C_element_mul = A .* B;     % -> [5 12; 21 32]

% 几乎所有的 MATLAB 性能优化,本质都是用“元素级运算”代替显式的 for 循环。

**3. 向量生成:告别 **for(i=a; i<=b; ++i)

% 冒号运算符: [start:step:end]
x1 = 1:5;                   % [1, 2, 3, 4, 5]
x2 = 0:0.5:2;               % [0, 0.5, 1, 1.5, 2]

% linspace: 指定点数,常用于绘图
x3 = linspace(0, 100, 5);   % 在 [0, 100] 之间取5个点 -> [0, 25, 50, 75, 100]

% 特殊矩阵
eye(3)      % 单位矩阵
zeros(2,4)  % 全零矩阵,类似 C++ 的 `vector<vector<int>>(2, vector<int>(4, 0));`
ones(3)     % 全1矩阵
rand(2,3)   % 随机矩阵

第三章:从代码片段到工程 —— 脚本与函数

C++ Coder D-e-v's Note: MATLAB 的 .m 文件有两种模式:脚本 (Script) 和函数 (Function),靠文件第一行有没有 function 关键字区分。

  • 脚本:就是 main 函数体。它直接在全局作用域执行,所有变量都是全局的。适合跑流程、做实验。

  • 函数:就是 C++ 的函数。它有独立的局部作用域,通过 return(输出参数列表)返回值。这是代码复用和模块化的唯一途径。

**1. 脚本文件:你的 **main.cpp

% file: my_script.m
% 解一个线性方程组 Ax=b
clear; clc; % 好习惯:脚本开头清空环境,避免被全局变量污染

A = [2 3; 1 -4];
b = [5; -3];
x = A \ b;  % Pro-Tip: '\'是矩阵左除,解Ax=b的专用运算符,比inv(A)*b更稳定高效

disp(['Solution: ', num2str(x')]); % disp 类似 cout,num2str 是 C++20 的 std::format

2. 函数文件:可复用的工具

结构就是一切function [返回列表] = 函数名(参数列表)

% file: average.m (文件名必须与函数名一致!)
function avg = average(x)
    % 这是一个计算向量平均值的函数
    % Input: x - 一个数值向量
    % Output: avg - 向量的平均值
    % C++ Coder's Note: 这是函数作用域,变量 n 和 s 都是局部的
    n = length(x);  % length 类似 C++ 的 .size()
    s = sum(x);     % sum 是一个超高效的内置函数
    avg = s / n;
end

% 在命令窗口或脚本中调用:
% >> my_vec = [1, 2, 3, 4];
% >> result = average(my_vec); % result = 2.5

第四章:逻辑控制:熟悉的味道,不同的语法

C++ Coder D-e-v's Note: 这里的逻辑和你早已掌握的一模一样,只是语法糖不同。注意所有控制结构都需要 end 关键字闭合。

**1. 条件语句 **if-elseif-else

score = 85;
if score >= 90
    disp('Excellent');
elseif score >= 80      % 注意,是 elseif
    disp('Good');
else
    disp('Pass');
end                     % 别忘了 end

**2. 循环结构:for 和 **while

% for 循环 (计数循环)
% for(int i=2; i<=100; i+=2)
sum_even = 0;
for i = 2:2:100
    sum_even = sum_even + i;
end

% while 循环 (条件循环)
a = 1; b = 1;
while b <= 100
    % disp(b);
    temp = a;
    a = b;
    b = temp + b;
end

% break 和 continue 和 C++ 里完全一样

第五章:数据可视化(核心优势之一)

C++ Coder D-e-v's Note: 这就是你选择 MATLAB 而不是 C++ 来做数据分析的理由。在 C++ 里用 gnuplot 或 Matplotlib-cpp 绘图有多痛苦,在 MATLAB 里就有多快乐。

% 绘制 y = sin(x) 和 y = cos(x)
x = linspace(-2*pi, 2*pi, 200); % x 轴数据点
y1 = sin(x);
y2 = cos(x);

figure; % 创建一个新的图形窗口,像 new 一个窗口对象

plot(x, y1, 'r-o', 'LineWidth', 2); % 红色、实线、圆圈标记
hold on; % 关键命令!不清空当前画布,准备画下一条线
plot(x, y2, 'b--x', 'LineWidth', 2); % 蓝色、虚线、x标记
hold off; % 释放画布

% 添加“UI”元素
grid on;
title('Sine and Cosine Functions');
xlabel('Radian');
ylabel('Value');
legend('sin(x)', 'cos(x)');

第六章:算法实现:从 C++ 思维到 MATLAB 思维

1. 素数检测:循环 vs. 向量化

% C++ 风格:用循环
function is_p = is_prime_loop(n)
    if n <= 1, is_p = false; return; end
    for i = 2:sqrt(n)
        if mod(n, i) == 0
            is_p = false; return;
        end
    end
    is_p = true;
end

% Matlab 风格:用内置函数和向量化
% isprime 是一个高度优化的内置函数
% isprime

平台差异与注意事项(面向 C++ 读者)

  • 索引与内存布局:MATLAB 1-based、列主序;C/C++ 常用 0-based、行主序。跨语言数据交互需注意转置与维度。
  • 值语义与拷贝:数组为值语义,写时复制(copy-on-write);循环中频繁扩容会触发重复分配,建议预分配 zeros/ones
  • 向量化边界:并非所有逻辑都应向量化,过度使用隐式扩展与匿名函数会增加开销;热点代码优先 bsxfun/内置函数或 parfor
  • JIT 与性能:现代 MATLAB 具 JIT 优化,但复杂控制流/动态类型仍可能抑制优化;必要时使用 mex(C/C++)实现热点路径。
  • I/O 与绘图:绘图句柄操作较多时注意 hold on/offdrawnow 的调用频率,避免 UI 卡顿。
  • 工程化组织:函数优先于脚本;使用 +pkg 命名空间与 classdef 组织大型项目;固定随机种子与版本记录以便复现实验。
评论友链评价 · 获得专属标记