
MATLAB零基础系列的第二篇。上一篇我们把软件装好、界面认了个大概这回来搞真正动手写代码之前必须搞明白的东西——变量和数据类型。说白了你今天写的每一行MATLAB代码本质上都是在跟变量打交道。家里有没有那种带标签的收纳箱MATLAB的变量就是类似的玩意儿——你在箱子里放东西然后在箱子上贴个标签以后你只需要喊标签名字就能把东西拿出来用。这篇的目标很简单让一个完全没写过代码的人看完之后能自己在命令行窗口里创建变量、修改变量、搞清楚这个变量是什么类型并且知道为什么MATLAB有时候会跟你抱怨“类型不对”。整篇都是大白话加实操建议打开你的MATLAB跟着敲一遍。1. 先搞清楚变量到底是个什么东西1.1 创建变量就是给数据贴标签打开MATLAB你会看到一个巨大的命令行窗口光标一闪一闪等着你输入。试着敲下面这行然后按回车a 10窗口里立刻显示a 10。恭喜你刚刚创建了人生中第一个MATLAB变量。注意中间那个等号。数学里它表示“等于”但在MATLAB里它的含义是“把右边的值装进左边这个名字里”。所以a 10的意思是在内存中找一块空间存入数值10然后把这块空间命名为a。以后你只要写一个aMATLAB就知道你要的是那个10。如果你不想让结果刷屏只需要在语句末尾加一个分号a 10;这条命令执行后窗口里什么都不显示但变量a已经存在了。分号是新手最容易被忽略的习惯。当年我刚学时前两周一跑脚本就满屏飘数字后来才知道全是分号惹的祸。赋值语句末尾加分号是一个值得从第一天就养成的肌肉记忆。1.2 变量会覆盖清空要小心继续操作a 20;这时候a里的10就被20覆盖了。同一个变量名同一时刻只能存一份数据你给a赋了新值旧值就没了。再来一次a [1 2 3];a又从数值变成了一个1行3列的数组。这说明MATLAB变量的类型可以随赋值内容随时改变这点和Python有些像和C语言那种定义好类型就不能变的思路完全不同。换句话说你不需要专门写一句“声明类型”的话赋值即创建、赋值即定类型。想删除某个变量用clear a想把所有变量一次性全删掉用clear或clear all。这里我要多说一句很多老手其实不推荐你没事就clear all尤其你在调试一个比较大的脚本时把工作区清空等于把你之前算好的中间结果全扔了万一没存盘只能从头再跑。更稳妥的做法是clear 变量名逐个清理。1.3 命名规则别踩这3个雷变量命名是零基础最容易犯错的环节。规则其实就三条必须以字母开头不能是数字开头。1a在MATLAB里是非法名字只能由字母、数字、下划线组成不能有空格、点号、加减号不能和MATLAB的关键字冲突比如if、for、while、end这些都不能当变量名。另外注意MATLAB是区分大小写的。a和A是两个完全不同的变量。这个问题害了无数新手——你在第五行定义了Data然后在第二十行写dataMATLAB立刻告诉你“未定义变量”你找了半小时才发现只是大小写对不上。我建议命名的时候用有意义的单词组合比如imageData、maxTemperature别用x1、x2、a1、b2这种毫无信息的名字。等你的脚本写到一百行你就会明白好名字有多重要。想检查某个名字能不能用MATLAB里有个函数isvarnameisvarname(1a)返回0isvarname(data_1)返回1。顺便说一句MATLAB没有C语言那种指针变量概念你不需要关心变量在内存里的具体地址变量名就是你访问数据的直接方式这让很多事情变简单了。1.4 认识一下那个默认变量 ans有个小细节新手一定会遇到你在命令行直接输入一个表达式然后回车比如5 3结果8会显示在屏幕上同时被存进一个叫ans的变量里。你可以输入ans回车查看它确实是8。但注意ans是个偷懒变量。你下次再计算2 * 9ans就被18覆盖了。所以真正写脚本的时候永远不要把重要的中间结果寄存在ans里它只适合你随手验算几个数。2. MATLAB里到底有哪些数据类型2.1 数值类型double是默认整数类型要主动指定MATLAB里有一条根深蒂固的规矩所有数值默认都是 double 类型。double 全称是“双精度浮点数”占8字节能表示极大范围的小数和整数也是绝大多数计算用到的类型。写x 3.14x就是 double写y 100y也是 double哪怕100是个整数它照样占8字节。除了 double还有 single单精度4字节、int8、uint8、int16、uint16、int32、uint32、int64、uint64 这些整数类型。名称里的 int 表示有符号整数uint 表示无符号整数后面的数字代表位数。位数越大能表示的数值范围越大占用的内存也越大。为什么要搞得这么复杂直接全部用 double 不就行了答案在于内存和场景。一张256×256的灰度图像如果所有像素都用 double 存需要 256×256×8 字节约512KB如果用 uint8 存只要64KB相差8倍。图像处理尤其是视频流处理的时候这种内存差距是致命的。所以很多图像处理库的默认数据格式就是 uint8范围0到255正好对应灰度值。用一个表格来总结最常用到的几类数值类型你可以截图存着类型占用内存表示范围常见用途double8字节约±1.8e308默认的万能计算类型single4字节约±3.4e38大规模矩阵压缩内存uint81字节0~255图像像素、串口数据int81字节-128~127小范围带符号数据uint162字节0~65535传感器原始数据int324字节约±21亿文件格式、一般计数创建这些类型的方法很简单调用对应函数single(3.14)、uint8(255)、int16(-100)。如果你把一个浮点数丢进uint8()括号里比如uint8(3.7)它会四舍五入变成4。如果把负数转成 uint8比如uint8(-1)结果直接变成0因为 uint8 表示不了负数。这种溢出行为新手容易懵记住一句话类型转换之前先想想目标类型的范围够不够。2.2 逻辑类型比较运算的产物逻辑类型是MATLAB的 boolean只有两个取值true 和 false在内部存储中分别对应数值1和0。你只要写一句比较运算结果就是逻辑类型age 18; isAdult age 18; result 5 3;isAdult和result的类型都是 logical。逻辑值最常见的使用场景有三个作为 if 条件、作为矩阵索引mask索引在图像处理里特别常用、以及和其他逻辑函数配合。你可以用logical(1)、logical(0)自己创建也可以把任意非零数值转成逻辑真。注意MATLAB里0是假、非0为真这个规则和很多编程语言一致。2.3 字符和字符串单引号双引号不是一回事字符类数据类型是MATLAB新手最容易混淆的一块。在R2016b之前MATLAB只有 char 类型用单引号括起来本质上是一个字符数组。比如str hello;str是一个1×5的字符数组你可以像操作数组一样操作它比如str(1)返回h。这其实是一个历史包袱MATLAB最初设计时就把字符串当成字符的数组来用。从R2016b开始MATLAB新增了 string 类型用双引号括起来str2 hello;str2是一个真正的字符串对象一个元素就是一个完整的字符串。换句话说hello在内存里是5个字符排成一排而hello是一个整体。两者之间用char()和string()可以互转但如果把 char 和 string 混在一起操作经常会出现你意想不到的结果。我的建议是2020年之后的MATLAB版本新代码里直接用 string 类型省心但如果你的代码要和第三方库、旧代码配合还是老老实实跟着旧风格走。这里有个经典例子注意看A 1结果是66。因为单引号的A是字符参与加法运算时自动转成了对应的ASCII码65再加1得到66。如果你用A 1行为完全不同。所以记住char 能当数值算string 不能。2.4 容器类型cell、struct和table数值、逻辑、字符这些是“基础材料”接下来这三个是“容器”专门用来装不同类型的数据。元胞数组cell用花括号{}创建能装任意类型、任意尺寸的数据c {1, hello, [1 2 3]; true, 3.14, world};这里c是一个2行3列的元胞数组第1行第1列是数值1第1行第2列是字符串互不干扰。访问时有个世纪难题c(1)和c{1}有什么区别c(1)取出的是一个1×1的元胞它本身还是 cell 类型c{1}取出里面装的实际内容。新手经常在这两种括号上翻车我的记忆技巧是花括号是“把锁撬开拿里面的东西”圆括号是“隔着箱子看包裹”。结构体struct用点号访问字段student.name 张三; student.score 98; student.id 2024001;这里student是一个结构体有三个字段 name、score、id。你还可以创建结构体数组student(2).name 李四; student(2).score 87;这样student就变成了1×2的结构体数组。结构体特别适合把一组相关但不同类型的数据包在一起比如一张图片的像素矩阵、标题、拍摄时间用 struct 一包传递起来非常省事。这就是热搜词里“结构体变量的定义”在MATLAB里的标准做法。表table长得像Excel表格t table([1;2;3], {张三;李四;王五}, VariableNames, {ID, 姓名});实际项目中 table 的威力很大列可以有不同的数据类型还能直接用列名访问t.ID做数据分析和机器学习的时候几乎天天用。零基础阶段你只需要知道有这个东西后面数据处理篇再深入展开。2.5 别忽略矩阵这个庞然大物最后要说一个MATLAB的底层思维在MATLAB里标量是一个1×1的矩阵向量是1×n或n×1的矩阵多维数组是n维矩阵。矩阵是MATLAB的“一等公民”你写a 5本质上获得了一个1×1的 double 矩阵。这也是MATLAB叫“矩阵实验室”的原因。所以这一篇里学的每一句赋值语法拿到矩阵场景下依然成立后面的数组与矩阵篇会接续展开。3. 查看变量类型与类型转换实操必备技能3.1 怎么知道一个变量是什么类型写脚本的时候经常要确认手里的变量到底是什么类型。我给新手推荐三个方法。第一看工作区窗口。MATLAB默认布局右上角有 Workspace 面板里面列出每个变量名、值、大小、类型点一下还能进一步查看数据内容。观察它比敲命令直观得多。第二用whos命令。在命令行输入whos会输出当前所有变量的名称、大小、字节数和 class。whos double可以只看指定类型。第三用class函数判断单个变量的类型。class(a)会返回double、char这样的字符串。配合isa可以写条件判断isa(a, double)返回 true 说明 a 是 double。这一组技能非常重要。图像处理场景下你从imread读进来一张图十有八九是 uint8但很多算法函数要求 double 参数你如果不查类型直接传进去要么报错要么结果不对。能自己判断类型等于你有了排查问题的第一个放大镜。3.2 类型转换别硬转先看范围类型转换就是让变量在类型之间迁移。常用函数前面已经提到double()、single()、int8()、uint8()等等。记住一个总原则转换之前先估一下目标类型能不能装下当前的数据特别是把浮点数转整数、把大范围的数转小范围类型的时候。几个实战场景场景一图像显示。imread读入的图是 uint8直接做运算可能溢出先转成 double 做计算完成后再转回 uint8 显示img imread(photo.jpg); % 读入图片uint8类型 img_d double(img); % 转 double 做计算 img_p img_d / 255; % 归一化到 0~1 imshow(uint8(img_p * 255)); % 显示前转回 uint8场景二字符和数值互转。num2str(3.14)得到3.14str2double(3.14)得到3.14。注意str2double比str2num健壮得多str2num内部会调用 eval有安全风险性能也差。我建议把str2num这个函数拉黑字符串转数值一律用str2double。场景三逻辑类型转换。logical(0)为 falselogical(5)为 true。在 mask 操作里特别常用图像处理后得到的数值数组转成逻辑索引就能按像素条件批量赋值。还有一件事要时刻记住MATLAB在数值运算中会做自动类型提升。比如uint8(200) double(100)uint8会先转成 double 再相加结果300。但uint8(200) uint8(100)呢结果不是300而是255——uint8运算后的结果还是 uint8溢出后饱和到最大值255。这个坑我在做图像像素操作时踩过无数次所以做加法前先确认运算双方是什么类型。3.3 数字显示格式看不全不等于丢了精度还有一个跟数值显示相关的命令初学者容易误解format。format long能显示更多小数位format short恢复默认的4位小数format bank显示为带两位小数的货币格式。要注意format只改变显示不改变存储在变量里的实际值。很多人看到显示5.0就以为自己算错了其实数据精度一直在只是显示器隐藏了而已。想看完整值用format long或者直接disp(x)。3.4 结合一下一个完整的变量实操小练习纸上谈兵结束来做一个综合小练习把变量、类型、转换串一遍。在命令行依次输入a 200; b uint8(100); c a b; d b b; whos第一行和第二行创建了一个 double 变量a和一个 uint8 变量b。第三行a b时 b 自动转为 double所以c是 double 类型的300。第四行两个 uint8 相加结果还是 uint8溢出饱和到255。用whos看到的四行信息清清楚楚展示出每个变量的类型差异。你可以试着把b改成uint8(255)b b的结果还是255因为饱和了改成uint8(127)结果就是254没有溢出。通过这种小实验你对“类型决定行为”会有非常直观的感受。4. 新手最容易踩的坑附解决方案4.1 变量名覆盖内置函数名这是MATLAB特有的坑。sum、mean、max这些名字既是内置函数也完全可以拿它们当变量名用但——你一旦定义了sum 100那整个工作区里sum就变成变量了你后面想调用sum()函数求和MATLAB只会一脸懵。解决办法命名习惯上不要用常用函数名当变量名。真不小心踩了清除变量clear sum就能恢复函数功能。这个坑的可怕之处在于它不报错只会在运行结果上出问题排查起来很费时间。4.2 大小写敏感前面说过MATLAB区分大小写。ImageData和imagedata是完全不同的两个变量。建议是从一开始就固定命名风格统一用驼峰命名法所有变量都按你定的风格来大小写问题自然消失。4.3 单引号双引号混用char 和 string 混在一起赋给同一个变量类型会在两个之间来回横跳代码里就会出现“点击运行成功换行报错”的诡异局面。解决办法在2.3节已经说了确定一套风格不要来回切换。4.4 忘记加分号导致输出刷屏严格来说这不是报错但会让你的命令行窗口变成一坨乱麻。我的习惯是赋值语句一律加分号只有明确想看的语句才不加。4.5 undefined function or variable变量真的没定义新手最常见报错是“未定义变量”。原因通常就几种变量名拼错了、大小写对不上、脚本里的执行顺序还没运行到赋值那行、或者你 clear 掉了。排查思路先用whos看看到底有没有这个变量再看看是不是大小写问题。4.6 cell花括号和圆括号的误用再强调一次c(1)取的是元胞c{1}取的是内容。如果从c(1)里取出来的东西是 cell 类型你拿去做数值运算就会报错。口诀圆括号取包裹花括号拆包裹。4.7 运行前忘记清理旧变量在脚本顶部修修改改每次运行都基于上一次留下的一堆变量。最典型的情况是你定义了一个循环变量 i上一次运行到100这次新代码里逻辑没覆盖到就出了问题。处理办法脚本开头用clear;确保环境干净。注意前面我建议不要随时clear all但脚本开头做一次全局清理是合理的。5. 抛开语法给零基础的你几个习惯建议学变量和数据类型真正难的永远不是语法而是习惯。我见过太多新手把代码写成一坨无法维护的变量海所以最后分享几个自己反复吃亏换来的习惯。第一给变量起名之前先想想这个变量未来会被谁读。不是只有别人会读三个月后的你也是“别人”。imageData、maxValue这种名字永远比x、y、a、b好。就算多敲几个字符换来的读代码效率提升是值得的。第二每写完一段脚本用whos看一遍变量清单发现没用的变量及时 clear 掉。这能帮助你保持一个干净清爽的工作区出问题时定位更快。第三变量赋值和类型转换尽量逐行写、逐行跑不要一次性写完一大坨再回来看。零基础阶段MATLAB的反馈速度就是你的学习速度。命令行窗口不像其他语言那样需要编译整个项目你敲一句它执行一句这是MATLAB对新手最大的友好之一。第四遇到类型转换相关的奇怪结果先打印class(input)和class(output)八成问题出在类型匹配上。这个技巧我到现在还在用。我记得自己当年第一次接触MATLAB就是在网上找了一段图像处理的代码复制粘贴运行报错无数后来实在没办法从头把变量和数据类型啃明白才发现原来一大半报错都是类型问题引起的。那一瞬间有种顿悟感不是代码难是基础没打牢。所以这一篇虽然看起来啰嗦但确实是你后面写任何MATLAB代码的根。把变量和数据类型这两块吃透再往下的数组、矩阵、循环、条件判断都会顺畅很多。