- 发表于
MATLAB入门教程:面向C++/OIer的数据可视化与科学计算指南
你好,C++ Coder / OIer!
你习惯于 main 函数、std::vector、#include,以及对性能和内存的极致追求。现在,你遇到了一位新工具:MATLAB。将它视为一个面向科学计算和 数据可视化 的交互式环境与计算工作台即可。这篇 MATLAB入门教程 将结合 C++ 的思维模式,帮助你尽快理解 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 | 查看工作区变量 | 变量监视窗口的文本版。whos 是 sizeof 和 typeid 的组合体。 |
cd | 切换工作目录 | chdir(),确保你的 .m 文件和数据在当前路径,否则就是 "File Not Found"。 |
2. 变量:动态类型的世界
C++ Coder D-e-v's Note: MATLAB 是动态强类型语言。你无需声明类型(int a; double b;),解释器会自动推断。但一旦类型确定,运算必须合法。
命名规则:和 C++ 类似,字母开头,可含数字、下划线。
最大陷阱:禁止覆盖内置函数! 如果你写
sum = 10;,就相当于你#define sum 10,std::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/off与drawnow的调用频率,避免 UI 卡顿。 - 工程化组织:函数优先于脚本;使用
+pkg命名空间与classdef组织大型项目;固定随机种子与版本记录以便复现实验。