MATLAB 在科学计算中的位置
MATLAB 的名字来自 “MATrix LABoratory”(矩阵实验室),它的设计起点就是用矩阵运算表达科学与工程问题。线性代数、信号处理、控制系统、数值优化、图像处理——在这些领域,MATLAB 提供的是“把数学公式直接翻译成代码”的体验,而不用先操心内存和指针。
它和通用语言的分工也很清楚:通用语言擅长构建软件系统,MATLAB 擅长快速验证算法与模型。做研究、做课程作业、做工程前期的方案仿真、做数据分析与出图,MATLAB 的开发效率通常明显更高。理解这一点,你就不会纠结“为什么不用 C 重写一遍”。
MATLAB 的哲学是“让研究者专注数学”。当你写 A * b 时,它真的就是在做矩阵乘法——语言层面为数学而生,而不是后来才拼装的库。
- 一切皆矩阵MATLAB 的基本数据类型就是数组,标量是 1×1 矩阵。
- 向量化优先整数组运算,避免逐元素循环。
- 脚本与函数脚本用于流程,函数用于复用与传参。
- Simulink用框图搭模型做动态系统仿真,不必手写微分方程求解器。
矩阵与数组:一切皆矩阵
在 MATLAB 里,连一个数字都是 1×1 的矩阵。创建矩阵用方括号,行内元素用空格或逗号分隔,换行(或分号)分隔不同行。默认下标从 1 开始,这也是它和多数编程语言最直观的差异。
% 创建矩阵与向量
A = [1 2 3; 4 5 6; 7 8 9]; % 3x3 矩阵
v = 1:5; % 行向量 1..5
w = (0:0.5:2)'; % 列向量(转置)
size(A) % 3 3
A' % 转置
A * v' % 矩阵乘法
A .* A % 对应元素相乘(点乘)
% 解线性方程组 A*x = b
b = [1; 1; 1];
x = A \ b; % 左除,数值稳定的求解
disp(x)
| 运算 | 符号 | 含义 |
|---|---|---|
| 矩阵乘 | * | 按线性代数规则相乘 |
| 数组乘 | .* | 对应位置元素相乘 |
| 左除 | \ | 解 Ax = b |
| 右除 | / | 解 xA = b |
| 幂 | ^ / .^ | 矩阵幂 / 元素逐项幂 |
最常踩的坑就是漏了点号:* 是矩阵乘法,.* 才是逐元素相乘。当你对两个同形数组做“逐项”运算(加减乘除幂)时,记得加上 .。反过来,解方程优先用 \ 而不是求逆再相乘——inv(A)*b 既慢又不稳定。
脚本、函数与流程控制
脚本(.m 文件)就是一段按顺序执行的命令集合,适合做一次性的计算与绘图;函数则封装输入输出,可被反复调用。现代 MATLAB 更推荐把函数写在各自文件里,或用 function 局部函数组织同一文件内的多个逻辑。
function [s, m] = stats_of(n)
% 计算 1..n 的和与平均值
s = 0;
for k = 1:n
s = s + k;
end
m = s / n;
end
% ---- 另一个脚本中调用 ----
[s, m] = stats_of(100);
fprintf("和 = %d,平均 = %.2f\n", s, m);
% 条件与逻辑
score = 87;
if score >= 90
grade = "A";
elseif score >= 60
grade = "B";
else
grade = "C";
end
disp(grade) % B
语法上要注意:函数返回值写在等号左边([s, m] = ...),不需要 return 语句结束;字符串既可以用单引号(字符数组)也可以用双引号(string 类型),处理文本建议统一用双引号;fprintf 用于格式化输出,disp 用于直接显示。
索引、切片与逻辑索引
MATLAB 的索引能力非常强,掌握它能省掉大量循环。圆括号用于取值,冒号表示“全部或范围”,end 代表最后一个下标;逻辑索引则用一个同形的逻辑数组挑出满足条件的元素。
A = magic(4); % 4x4 魔方矩阵
A(1, 2) % 第 1 行第 2 列
A(2, :) % 第 2 行全部
A(:, 3) % 第 3 列全部
A(2:3, 1:2) % 子矩阵
% 逻辑索引:挑出大于 10 的元素
idx = A > 10;
big = A(idx); % 拉直成列向量
A(idx) = 0; % 把满足条件的位置清零
% 常用汇总
sum(A(:)) % 所有元素之和
max(A, [], 2) % 每行最大值
特别注意:MATLAB 的数组是按列优先存储的,A(:) 会把矩阵按列拉直成一个长列向量。max、min、sum 默认按列运算,要按行就得显式给维度参数(如 max(A, [], 2))。这两个习惯一旦建立,写出来的代码会简洁很多。
二维与三维绘图
可视化是 MATLAB 的招牌能力之一:几行命令就能得到可出版的图表。绘图的基本套路是“先准备数据,再调用绘图函数,最后加标注与网格”。
% 二维曲线
t = 0:0.01:2*pi;
y1 = sin(t);
y2 = cos(t);
figure;
plot(t, y1, 'LineWidth', 1.5); hold on;
plot(t, y2, '--', 'LineWidth', 1.5);
xlabel('t'); ylabel('值');
legend('sin(t)', 'cos(t)');
title('正弦与余弦'); grid on;
% 三维曲面
[X, Y] = meshgrid(-2:0.1:2, -2:0.1:2);
Z = X .* exp(-X.^2 - Y.^2);
figure;
surf(X, Y, Z); shading interp;
colorbar; xlabel('X'); ylabel('Y'); zlabel('Z');
几个实用习惯:用 hold on 在同一张图上叠加多条曲线;用 figure 显式新建窗口,避免覆盖上一张图;shading interp 让曲面过渡更平滑。meshgrid 是画三维曲面的关键——它把一维坐标扩展成二维网格,从而能对每个 (x, y) 组合求值。
Simulink 仿真入门
Simulink 是 MATLAB 家族里做动态系统仿真的图形化环境。你不必手写微分方程和数值积分,而是用框图把系统搭出来:信号源、增益、积分器、求和节点、示波器,连线即可运行,结果实时查看。
一个最小的弹簧—阻尼系统仿真,可以这样搭:
- 用 Step(阶跃)或 Sine Wave(正弦)模块作为输入激励。
- 用 Gain 模块表示系数(如阻尼比、刚度系数)。
- 用 Integrator 模块对状态导数积分,得到速度与位移。
- 用 Sum 模块做加减,把各项按物理关系连接。
- 用 Scope 模块观察输出曲线,必要时导出数据到工作区继续分析。
与“手写脚本求解”相比,Simulink 的优势在于可视化与可修改性:换一个参数、加一个反馈环、接入控制器,都只是拖动模块和改数值的功夫。工程上常把 Simulink 用作控制算法验证与系统级仿真的平台,再把它转成嵌入式代码部署到硬件。
实战:求解并可视化一个微分方程
把矩阵运算、函数句柄与绘图串起来,求解一个一阶线性微分方程 dy/dt = -0.5 y + sin(t),初值 y(0) = 1,并画出解曲线。
% 定义方程右端(匿名函数)
f = @(t, y) -0.5 * y + sin(t);
% 用 ode45 自适应求解,时间区间 [0, 20]
[t, y] = ode45(f, [0, 20], 1);
% 解析解(线性方程可用积分因子)
yExact = @(t) (0.4*cos(t) + 0.8*sin(t)) + 0.6 * exp(-0.5 * t);
% 绘图对比
figure;
plot(t, y, 'o-', 'LineWidth', 1.2); hold on;
tt = linspace(0, 20, 400);
plot(tt, yExact(tt), '--', 'LineWidth', 1.2);
xlabel('t'); ylabel('y');
legend('数值解 (ode45)', '解析解');
title('一阶线性微分方程求解'); grid on;
% 数值解的稳定性检查
fprintf("最大误差 = %.4f\n", max(abs(y - yExact(t))));
这段代码示范了真实科学计算的完整流程:把方程写成匿名函数 → 交给 ode45 做自适应步长数值求解 → 叠加解析解做交叉验证 → 出图并量化误差。ode45 基于 Runge–Kutta 方法,对大多数非刚性方程都很可靠;如果发现求解极慢或结果发散,再考虑换用适合刚性问题的 ode15s。
学习建议与工程实践
入门路径建议是:先熟悉矩阵创建、索引与向量化运算,再学函数与绘图,然后针对自己的领域(信号、控制、优化、图像)选一两个官方示例跑通,最后过渡到 Simulink。官方文档与示例库是最好的教材,遇到函数记不清就查帮助文档。
- 优先向量化:能用数组运算就别写
for,速度可能相差几十倍。 - 预分配数组:循环里往数组追加元素会反复扩容,先用
zeros(1, N)预分配。 - 加注释与分节:用
%%把脚本分节,可单独执行某一段,便于调试。 - 保存为函数:验证成功的代码固化成
.m函数,下次直接复用。 - 注意数值精度:比较浮点数尽量不要直接用
==,用容差判断。
MATLAB 最大的价值,是把“从数学到结果”的距离压缩到最短。把向量化与可视化两个习惯练熟,你处理科学计算问题的效率会有质的提升。
到这里,「主流编程语言」频道的七个子分类都已就位:C 与 C++ 打底内存与性能,C# 与 VB.NET 面向 .NET 应用,R 与 MATLAB 服务数据分析与科学计算,Rust 用所有权重新定义内存安全。按自己的方向选一门先跑起来,比反复比较更有效。