1.2 Matlab基本语法:为矩阵而生的语言


1.2 Matlab 基本语法:为矩阵而生的语言

本节摘要:Matlab 的变量默认是双精度矩阵,运算符默认按矩阵语义解释。本节讲清变量与数据类型、两类运算符的区分(矩阵运算与数组运算)、控制流语句,重点是与通用语言不同的语义规则。

为什么初学者会踩同一批坑

从 Python 或 C 迁移过来的人,几乎都在两个地方翻过车:一是以为 2^1/2 会得到 2 的平方根(实际从左到右算,结果就是 1);二是用 * 乘两个维度不匹配的矩阵直接报错,因为 Matlab 的 * 是矩阵乘法,不是逐元素乘。这些"坑"不是设计缺陷——在 1980 年代的定位里,Matlab 的用户默认懂数值线性代数,运算符自然选了数学语义。

变量与数据类型

Matlab 是动态类型语言,变量无需声明。但"默认双精度矩阵"这件事从第一天就没变过:

x = 3.14 % 1x1 矩阵,double 类型 v = [1 2 3] % 行向量 M = [1 2; 3 4] % 2x2 矩阵,分号换行 s = 'matlab' % 字符数组(老派写法) str = "matlab" % string 类型(R2016b 引入,演化痕迹明显) c = {1, 'a', [1 2]} % 元胞数组:类型混杂的容器

演化痕迹值得注意:string 双引号类型出现得很晚,此前字符串处理全靠字符数组,这也是大量老代码里 strcatsprintf 遍地的原因。新代码建议统一用 string。

类型判断用 class(x),转换用 doubleint32 这类函数。工程上一个常见决策是图像数据:uint8 存储省内存,但运算前要转 double,否则 uint8 的饱和截断会把 250+10 变成 255。

两套运算符:矩阵语义与数组语义

运算 矩阵语义 数组语义(逐元素)
A*B A.*B
A\b(左除)、/(右除) A./B
A^2 A.^2
转置 A'(共轭转置) A.'(普通转置)

一个点,区分了整门线性代数和逐元素运算。写数值代码时的经验法则:想清楚这一步在数学上是矩阵变换还是逐点函数,语法自然就对了。

A = [1 2; 3 4]; B = A * A % 矩阵平方:A两次作用 C = A .^ 2 % 每个元素自己平方

控制流:后加的楼层

if/for/while 语法上和 C 系语言接近,但两点不同:块用 end 关闭而非花括号;for 遍历的是矩阵的每一列。

for k = 1:5 % 1:5 生成行向量,k 依次取每列 fprintf('k = %d\n', k); end n = 0; while n < 3 n = n + 1; end

for 遍历列这个设定看似冷僻,却是矩阵中心主义的自然结果——连循环变量都是矩阵。第 6 章会讲为什么在 Matlab 里应当尽量少写显式循环,向量化才是母语写法。

⚠️ 常见坑:变量名覆盖内置函数。给变量取名 summeanlength 之后,这些函数在你 clear 之前全部失效,报错信息还往往指向别处。

类型系统全景与选型

把常用类型放进一张表,工程里怎么选就清楚了:

类型 典型构造 适合存什么 注意点
double 默认 数值计算主力 占 8 字节/元素,大数组费内存
single single(x) 大规模数据、GPU 计算 精度约 7 位有效数字
uint8 uint8(x) 图像像素、传感器原始值 溢出饱和到 255,不回绕
logical A > 10 掩码、条件筛选 可当索引用,占 1 字节
cell {...} 异构集合、变长表格 取内容用花括号
struct s.name = ... 带字段名的记录 字段可再嵌套

整数类型的饱和行为值得单独演示一次,印象最深刻:

a = uint8(250); b = a + 10 % 结果是 255,不是 260 c = double(a) + 10 % 先转 double 再算,得到 260

第一行输出 255 而不是 260,因为 uint8 到顶就截住。图像处理里把这一步忘了,几百行代码的统计结果会整体偏低且无任何报错——这是静默错误,比崩溃更难查。

元胞与结构体的取用辨析

初学者最容易混的两对括号:圆括号取元胞"盒子",花括号取盒子里面的"东西"。

c = {rand(3), 'text'}; box = c(1); % 1x1 元胞,里面装着矩阵 val = c{1}; % 3x3 矩阵本身 size(box) % 输出 1 1 size(val) % 输出 3 3

结构体则走另一条路,字段名即语义:

run.trial = 1; run.data = rand(100,2); run.note = "baseline"; runs = repmat(run, 4, 1); % 批量做 4 次实验记录 runs(2).trial = 2;

选型经验:元素结构一致、想整体做运算,用矩阵;元素类型各异但位置有序,用元胞;每个元素有明确字段语义、要按名字访问,用结构体数组。实验记录这类场景,结构体数组的可读性远胜元胞。

控制流里的浮点陷阱

while 配浮点条件是另一个经典雷区。下面这段代码在有些机器上会多循环一次甚至不终止:

x = 0; n = 0; while x < 1 x = x + 0.1; n = n + 1; end % 期望 n=10,实际常常是 11:0.1 的二进制表示略大

原因是 0.1 在二进制里不能精确表示,十次累加后 x 略大于 1 的判定会推迟或提前。工程写法是给比较留容差:用 while abs(x - 1) > 1e-9 这类带容差的条件,或者干脆改用整数计数控制循环。

本节要点回顾

  • 一切皆矩阵:标量是 1x1,变量动态创建,默认 double;
  • 一个点两个世界* 是矩阵乘、.* 是逐元素乘,除法与幂同理;
  • A\b 直接解方程,这是从 LINPACK 时代继承的看家语法;
  • 字符串有新旧两代:字符数组与 string,新代码选后者;
  • 循环遍历列,块以 end 收尾,避开内置函数名做变量名。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U