深度解析:從sqrt、abs到tinv與plot的實(shí)戰(zhàn)應(yīng)用)
1. 項(xiàng)目概述從課后習(xí)題到實(shí)戰(zhàn)工具箱很多朋友在學(xué)MATLAB入門課程時(shí)可能會(huì)覺(jué)得課后習(xí)題里的函數(shù)講解就是“講完就完事了”。但以我十多年的工程和教學(xué)經(jīng)驗(yàn)來(lái)看恰恰是這些習(xí)題里拓展的函數(shù)構(gòu)成了你從“知道怎么用”到“知道什么時(shí)候用、為什么用”的關(guān)鍵橋梁。這門課的第3章課后習(xí)題表面上是鞏固基礎(chǔ)實(shí)際上是在幫你搭建一個(gè)最常用、最核心的“初級(jí)工具箱”。這個(gè)“工具箱”里的函數(shù)比如sqrt,abs看起來(lái)簡(jiǎn)單得不能再簡(jiǎn)單但你真的理解它們?cè)诓煌瑪?shù)據(jù)場(chǎng)景下的表現(xiàn)嗎比如習(xí)題里可能會(huì)讓你用sqrt求一個(gè)向量的平方根這背后就涉及到對(duì)數(shù)組運(yùn)算Array Operations的深刻理解——MATLAB的威力正在于此。又或者講到abs求絕對(duì)值它不僅能處理實(shí)數(shù)還能處理復(fù)數(shù)返回復(fù)數(shù)的模magnitude這個(gè)特性在信號(hào)處理、復(fù)數(shù)運(yùn)算中至關(guān)重要但初學(xué)者往往只記住了“取正數(shù)”這個(gè)片面印象。所以本章的拓展函數(shù)講解目的絕不是讓你死記硬背幾個(gè)函數(shù)名。它的深層價(jià)值在于通過(guò)具體的、有背景的習(xí)題引導(dǎo)你理解MATLAB函數(shù)設(shè)計(jì)的哲學(xué)掌握如何查閱幫助文檔并初步建立“根據(jù)問(wèn)題選函數(shù)”的思維模式。接下來(lái)我就把這些習(xí)題中常見(jiàn)的拓展函數(shù)掰開(kāi)揉碎了講不僅告訴你怎么用更告訴你為什么用、用的時(shí)候坑在哪。2. 核心數(shù)學(xué)運(yùn)算函數(shù)深度解析課后習(xí)題里首先繞不開(kāi)的就是最基礎(chǔ)的數(shù)學(xué)函數(shù)。這些函數(shù)是構(gòu)建一切復(fù)雜運(yùn)算的磚瓦。2.1 平方根函數(shù)sqrt不僅僅是開(kāi)根號(hào)sqrt(x)這個(gè)函數(shù)小學(xué)生都知道是開(kāi)平方。但在MATLAB里它的內(nèi)涵要豐富得多?;居梅ㄅc數(shù)組化運(yùn)算最直接的用法就是sqrt(4)返回2。但MATLAB的核心優(yōu)勢(shì)是矩陣運(yùn)算所以sqrt天然支持對(duì)數(shù)組和矩陣的逐元素操作。例如A [4, 9; 16, 25]; B sqrt(A)結(jié)果B將是[2, 3; 4, 5]。習(xí)題中常設(shè)計(jì)此類操作就是為了讓你習(xí)慣“向量化思維”避免寫低效的循環(huán)。對(duì)復(fù)數(shù)域的支持這是容易被忽略但極其重要的一點(diǎn)。sqrt函數(shù)同樣支持復(fù)數(shù)輸入。例如sqrt(-1)在MATLAB中會(huì)直接返回0.0000 1.0000i即虛數(shù)單位i。其計(jì)算遵循數(shù)學(xué)定義若z r*(cosθ i*sinθ)則sqrt(z) sqrt(r)*(cos(θ/2) i*sin(θ/2))。在涉及頻域分析、控制系統(tǒng)根軌跡繪制時(shí)這個(gè)特性是基礎(chǔ)。注意事項(xiàng)與實(shí)操心得輸入為非負(fù)實(shí)數(shù)當(dāng)輸入為負(fù)數(shù)時(shí)sqrt會(huì)自動(dòng)進(jìn)入復(fù)數(shù)域進(jìn)行計(jì)算。如果你期望的結(jié)果是實(shí)數(shù)且確認(rèn)數(shù)據(jù)應(yīng)為非負(fù)得到復(fù)數(shù)結(jié)果往往意味著數(shù)據(jù)前期處理有誤比如某個(gè)本應(yīng)為正數(shù)的計(jì)算值由于精度問(wèn)題變成了一個(gè)極小的負(fù)數(shù)。這時(shí)可以考慮使用realsqrt(x)函數(shù)它要求輸入必須為非負(fù)實(shí)數(shù)計(jì)算速度稍快且能起到數(shù)據(jù)校驗(yàn)的作用。數(shù)值穩(wěn)定性對(duì)于非常接近0的正數(shù)直接開(kāi)方是安全的。但要警惕“負(fù)零”問(wèn)題。在數(shù)值計(jì)算中一個(gè)理論上應(yīng)為0的數(shù)可能由于浮點(diǎn)誤差表現(xiàn)為一個(gè)極小的負(fù)數(shù)如-1e-16。sqrt會(huì)將其視為負(fù)數(shù)并返回復(fù)數(shù)。解決方法是在開(kāi)方前做一個(gè)“修剪”x(x 0 abs(x) 1e-10) 0;。矩陣開(kāi)方 vs.sqrtm千萬(wàn)注意sqrt(A)是對(duì)矩陣A的每個(gè)元素單獨(dú)開(kāi)平方。而矩陣的平方根是另一個(gè)概念指找到一個(gè)矩陣B使得B*B A。這需要調(diào)用sqrtm(A)函數(shù)。兩者天差地別混淆是常見(jiàn)錯(cuò)誤。2.2 絕對(duì)值函數(shù)abs實(shí)與復(fù)的統(tǒng)abs(x)函數(shù)同樣是一個(gè)“雙面手”。實(shí)數(shù)與復(fù)數(shù)的不同含義對(duì)于實(shí)數(shù)xabs(x)返回其絕對(duì)值非負(fù)值。對(duì)于復(fù)數(shù)z a biabs(z)返回其模magnitude計(jì)算公式為sqrt(a^2 b^2)。例如abs(3 4i)返回5。在習(xí)題中的典型應(yīng)用場(chǎng)景誤差計(jì)算在數(shù)值迭代算法中常需要計(jì)算當(dāng)前近似值與真實(shí)值或上一次迭代值的絕對(duì)誤差這時(shí)abs(x_true - x_approx)是標(biāo)準(zhǔn)操作。信號(hào)幅度在處理信號(hào)數(shù)據(jù)時(shí)abs常用于獲取信號(hào)的幅度信息。例如對(duì)一個(gè)復(fù)數(shù)頻域信號(hào)取abs就能得到幅度譜。判斷收斂在循環(huán)中常用abs(差值) 容差作為迭代終止條件。復(fù)數(shù)數(shù)據(jù)的可視化當(dāng)需要繪制復(fù)數(shù)序列的“大小”時(shí)abs是必用函數(shù)。比如plot(abs(complex_signal))。一個(gè)容易踩的坑abs對(duì)邏輯數(shù)組的影響MATLAB中邏輯值logicaltrue和false在數(shù)值運(yùn)算中分別被視為1和0。因此abs(true)返回1abs(false)返回0。這通常不會(huì)引起問(wèn)題但如果你無(wú)意中對(duì)一個(gè)邏輯索引數(shù)組使用了abs可能會(huì)得到意想不到的數(shù)值結(jié)果而非邏輯結(jié)果。在編寫條件判斷或索引時(shí)要確保數(shù)據(jù)類型清晰。2.3 深入理解tinv函數(shù)連接概率統(tǒng)計(jì)與區(qū)間估計(jì)在稍微進(jìn)階的習(xí)題中可能會(huì)引入統(tǒng)計(jì)學(xué)函數(shù)tinv就是一個(gè)典型代表。它不屬于最基礎(chǔ)的算術(shù)運(yùn)算但卻是數(shù)據(jù)分析、假設(shè)檢驗(yàn)如t檢驗(yàn)的基石。函數(shù)定義與數(shù)學(xué)原理tinv(P, nu)用于計(jì)算學(xué)生t分布的逆累積分布函數(shù)。通俗地講給定一個(gè)概率值P例如0.975和自由度nu它返回一個(gè)臨界值t使得在該t分布下從負(fù)無(wú)窮到t的累積概率等于P。數(shù)學(xué)上如果隨機(jī)變量T服從自由度為nu的t分布那么P Pr(T t)。tinv就是根據(jù)P求t。核心應(yīng)用置信區(qū)間的計(jì)算這是tinv最經(jīng)典的應(yīng)用。當(dāng)我們用樣本均值x_bar估計(jì)總體均值并希望構(gòu)建一個(gè)置信水平為(1-alpha)*100%的置信區(qū)間時(shí)區(qū)間半寬margin of error的計(jì)算公式為半寬 t_{alpha/2, nu} * (s / sqrt(n))其中s是樣本標(biāo)準(zhǔn)差n是樣本量nu n - 1是自由度t_{alpha/2, nu}就是通過(guò)tinv(1-alpha/2, nu)計(jì)算得到的臨界值。例如對(duì)于95%的置信區(qū)間alpha0.05alpha/20.025我們需要的是tinv(0.975, nu)。與ttest函數(shù)族的關(guān)聯(lián)熱搜詞中提到了ttest和ttest2。ttest用于單樣本或配對(duì)樣本t檢驗(yàn)ttest2用于獨(dú)立雙樣本t檢驗(yàn)。這些函數(shù)內(nèi)部會(huì)自動(dòng)計(jì)算t統(tǒng)計(jì)量并與臨界值比較而這個(gè)臨界值的計(jì)算就用到了tinv。理解tinv能讓你更透徹地理解t檢驗(yàn)報(bào)告中的t值和p值之間的關(guān)系甚至在不使用現(xiàn)成檢驗(yàn)函數(shù)時(shí)自己手動(dòng)實(shí)現(xiàn)檢驗(yàn)邏輯。實(shí)操要點(diǎn)與常見(jiàn)錯(cuò)誤參數(shù)順序與含義務(wù)必記住tinv(P, nu)。第一個(gè)參數(shù)是累積概率P范圍在0到1之間第二個(gè)是自由度nu必須是正數(shù)。順序反了或者P值給錯(cuò)如用了alpha而不是1-alpha/2是導(dǎo)致結(jié)果錯(cuò)誤的主要原因。單尾與雙尾在假設(shè)檢驗(yàn)中要區(qū)分單尾檢驗(yàn)和雙尾檢驗(yàn)。對(duì)于雙尾檢驗(yàn)若顯著性水平為alpha則查找tinv(1-alpha/2, nu)對(duì)于單尾檢驗(yàn)右側(cè)則查找tinv(1-alpha, nu)。混淆會(huì)導(dǎo)致置信區(qū)間或拒絕域錯(cuò)誤。自由度的確定對(duì)于單樣本均值檢驗(yàn)nu n-1。對(duì)于獨(dú)立雙樣本檢驗(yàn)假設(shè)方差相等nu n1 n2 - 2。這是另一個(gè)容易出錯(cuò)的地方。3. 數(shù)據(jù)操作與文件管理函數(shù)精講除了純數(shù)學(xué)計(jì)算習(xí)題還會(huì)涉及數(shù)據(jù)的“搬運(yùn)”和“管理”這是從腳本走向?qū)嶋H項(xiàng)目的第一步。3.1 數(shù)組索引與多列提取A(:, [col1, col2, ...])熱搜詞中提到了“matlab數(shù)組取出多列”這確實(shí)是數(shù)據(jù)處理的高頻操作。其語(yǔ)法非常直觀A(:, indices)。原理與語(yǔ)法:代表所有行。indices可以是一個(gè)標(biāo)量、一個(gè)向量或者邏輯數(shù)組。例如A(:, 3)取第3列A(:, [1,3,5])取第135列A(:, end)取最后一列。更靈活的可以用邏輯索引cols_to_keep [true, false, true, false]; B A(:, cols_to_keep);這將提取第1和第3列。在習(xí)題中的應(yīng)用模式習(xí)題不會(huì)直接考語(yǔ)法而是將其融入場(chǎng)景特征選擇假設(shè)一個(gè)矩陣data的每一列是一個(gè)特征你需要分析其中某幾個(gè)特征的關(guān)系就可以用selected_features data(:, feature_indices);。數(shù)據(jù)拆分將數(shù)據(jù)集拆分為訓(xùn)練集和測(cè)試集時(shí)經(jīng)常需要分別提取特征列和標(biāo)簽列。例如X data(:, 1:end-1); % 所有行除最后一列外y data(:, end); % 所有行最后一列。重新排列列順序new_order [3,1,2]; rearranged_data data(:, new_order);。性能與內(nèi)存考量對(duì)于大型矩陣頻繁創(chuàng)建新的子數(shù)組副本會(huì)消耗內(nèi)存和時(shí)間。如果只是讀取而不修改這種操作是高效的。但如果后續(xù)需要修改子數(shù)組并希望同步修改原數(shù)組則需要更高級(jí)的句柄或面向?qū)ο缶幊碳记伞?duì)于初學(xué)者建立“提取即副本”的概念很重要。3.2 文件操作函數(shù)movefile自動(dòng)化整理輸出movefile函數(shù)用于移動(dòng)或重命名文件和文件夾。在課后習(xí)題中它可能出現(xiàn)在需要自動(dòng)化保存或整理結(jié)果的場(chǎng)景里?;菊Z(yǔ)法movefile(source, destination)將source移動(dòng)至destination。movefile(source, destination, f)強(qiáng)制移動(dòng)即使目標(biāo)存在也覆蓋。典型應(yīng)用場(chǎng)景自動(dòng)化歸檔結(jié)果你的腳本生成了一個(gè)圖表并保存為figure1.png。在腳本末尾你可以使用movefile(figure1.png, results/weekly_report/figure1.png)將其自動(dòng)移動(dòng)到指定的歸檔文件夾。如果目標(biāo)文件夾不存在需要先用mkdir創(chuàng)建。批量文件處理結(jié)合dir函數(shù)和循環(huán)可以批量移動(dòng)符合特定模式的文件。例如將當(dāng)前文件夾下所有.txt文件移動(dòng)到text_files文件夾files dir(*.txt); for i 1:length(files) movefile(files(i).name, fullfile(text_files, files(i).name)); end重命名當(dāng)source和destination在同一目錄下時(shí)效果就是重命名。例如movefile(oldname.txt, newname.txt)。避坑指南路徑分隔符在Windows上使用反斜杠\在Linux/Mac上使用正斜杠/。為了代碼跨平臺(tái)建議使用fullfile函數(shù)來(lái)構(gòu)建路徑如movefile(source, fullfile(folder, subfolder, file.txt))。權(quán)限問(wèn)題如果沒(méi)有目標(biāo)目錄的寫入權(quán)限或源文件被其他程序占用操作會(huì)失敗。在腳本中可以使用try-catch語(yǔ)句來(lái)優(yōu)雅地處理此類錯(cuò)誤。f選項(xiàng)的風(fēng)險(xiǎn)強(qiáng)制覆蓋選項(xiàng)f非常有用但要慎用因?yàn)樗鼤?huì)不加提示地覆蓋目標(biāo)位置已有的同名文件可能導(dǎo)致數(shù)據(jù)丟失。在重要操作前可以先用exist(destination, file)檢查文件是否存在。4. 可視化與圖形定制函數(shù)實(shí)戰(zhàn)MATLAB“圖”出名門課后習(xí)題必然包含繪圖相關(guān)函數(shù)的拓展。這里挑兩個(gè)有代表性的講。4.1plot函數(shù)與RGB顏色指定讓圖表更專業(yè)熱搜詞提到了“matlab plot 畫(huà)rgb顏色”。在plot中指定顏色是美化圖形、區(qū)分多條曲線的關(guān)鍵。指定顏色的方法字符代碼最快捷的方式如r紅色b藍(lán)色g綠色k黑色等。RGB三元組這是更靈活、能實(shí)現(xiàn)精確色彩控制的方法。格式為[R, G, B]每個(gè)分量是0到1之間的浮點(diǎn)數(shù)。例如紅色[1, 0, 0]深藍(lán)色[0, 0.2, 0.6]自定義灰色[0.5, 0.5, 0.5]在plot中的應(yīng)用x 0:0.1:2*pi; y1 sin(x); y2 cos(x); % 使用RGB三元組指定顏色和線寬 plot(x, y1, Color, [0.85, 0.33, 0.10], LineWidth, 2); % 一種橙色 hold on; plot(x, y2, Color, [0, 0.45, 0.74], LineWidth, 2); % 一種藍(lán)色 hold off;這樣畫(huà)出來(lái)的圖顏色比簡(jiǎn)單的r和b更柔和、更專業(yè)尤其適合需要出版或做演示的場(chǎng)景。高級(jí)技巧從顏色映射中獲取顏色如果你有一組曲線想用當(dāng)前顏色映射colormap中的顏色來(lái)區(qū)分可以這樣做num_lines 5; colors parula(num_lines); % 獲取 parula 顏色映射的5種顏色 for i 1:num_lines plot(x, y_matrix(:, i), Color, colors(i, :)); hold on; end hold off;這能確保曲線顏色過(guò)渡自然且與圖中可能存在的色標(biāo)colorbar保持一致。4.2 坐標(biāo)軸截?cái)嗯c定制xlim,ylim及更多“matlab的橫坐標(biāo)如何截?cái)唷笔强梢暬械某R?jiàn)需求核心函數(shù)是xlim和ylim?;窘?cái)鄕lim([xmin, xmax])和ylim([ymin, ymax])直接設(shè)置坐標(biāo)軸的范圍。例如如果你只關(guān)心x從10到20的部分可以xlim([10, 20])。這比畫(huà)完圖再手動(dòng)縮放要精確和可重復(fù)。在習(xí)題中的應(yīng)用習(xí)題可能要求你繪制一個(gè)函數(shù)但只突出顯示其特定區(qū)間如零點(diǎn)附近、極值點(diǎn)附近或者比較多個(gè)子圖時(shí)統(tǒng)一坐標(biāo)軸范圍以便比較。不僅僅是截?cái)嗑?xì)控制xlim返回當(dāng)前坐標(biāo)軸的范圍可以將其保存下來(lái)。[xmin, xmax] xlim;。你還可以設(shè)置模式為手動(dòng)或自動(dòng)xlim(auto)讓MATLAB自動(dòng)選擇范圍。xlim(manual)凍結(jié)當(dāng)前范圍后續(xù)添加新圖形元素不會(huì)改變它。關(guān)聯(lián)技巧axis函數(shù)axis函數(shù)功能更強(qiáng)大可以一次性設(shè)置x和y軸范圍甚至縱橫比。axis([xmin xmax ymin ymax])等價(jià)于分別調(diào)用xlim和ylim。axis equal設(shè)置縱橫比使數(shù)據(jù)單元在x軸和y軸上具有相同的長(zhǎng)度。axis tight將坐標(biāo)軸范圍設(shè)置為恰好等于數(shù)據(jù)范圍。一個(gè)常見(jiàn)問(wèn)題截?cái)嗪髨D形“出界”當(dāng)你用xlim截?cái)嗪笾袄L制的圖形如線條、散點(diǎn)在范圍之外的部分默認(rèn)會(huì)被“裁剪”掉看不見(jiàn)。但有時(shí)你可能希望看到圖形延伸到邊界之外比如一條趨勢(shì)線。這時(shí)你需要設(shè)置圖形的裁剪行為h plot(x, y); h.Clip off; % 關(guān)閉裁剪允許圖形繪制在坐標(biāo)軸區(qū)域之外這個(gè)屬性在繪制箭頭、標(biāo)注線等需要超出當(dāng)前視圖的圖形元素時(shí)非常有用。5. 函數(shù)類型與編程概念延伸課后習(xí)題的拓展最終會(huì)引導(dǎo)你思考MATLAB中不同的“函數(shù)”概念這是邁向高級(jí)編程的臺(tái)階。5.1 內(nèi)置函數(shù) vs. 用戶自定義函數(shù) vs. 匿名函數(shù)MATLAB中有多種函數(shù)形式理解它們的區(qū)別和適用場(chǎng)景至關(guān)重要。內(nèi)置函數(shù) (Built-in Functions)如sqrt,abs,plot,mean等是MATLAB核心的一部分用編譯語(yǔ)言如C實(shí)現(xiàn)執(zhí)行效率最高。我們無(wú)法查看其源代碼type sqrt會(huì)顯示是內(nèi)置函數(shù)。課后習(xí)題主要拓展的就是這類函數(shù)的使用技巧。用戶自定義函數(shù) (User-Defined Functions)保存在獨(dú)立的.m文件中以function關(guān)鍵字開(kāi)頭。例如創(chuàng)建一個(gè)calculate_area.m文件function area calculate_area(radius) % CALCULATE_AREA 計(jì)算圓的面積 area pi * radius.^2; end這是封裝可重用代碼塊的主要方式。習(xí)題在后期會(huì)引導(dǎo)你從使用內(nèi)置函數(shù)過(guò)渡到編寫自己的函數(shù)。匿名函數(shù) (Anonymous Functions)熱搜詞中提到了“箭頭函數(shù)寫法”這通常指JavaScript的箭頭函數(shù)。在MATLAB中對(duì)應(yīng)的概念是匿名函數(shù)使用符號(hào)定義。% 定義一個(gè)計(jì)算平方的匿名函數(shù) square (x) x.^2; y square(5); % y 25 % 定義更復(fù)雜的匿名函數(shù) hypotenuse (a, b) sqrt(a.^2 b.^2); c hypotenuse(3, 4); % c 5匿名函數(shù)特別適合作為參數(shù)傳遞給其他函數(shù)函數(shù)句柄例如fplot((x) sin(x)./x, [-10, 10])??焖俣x簡(jiǎn)單操作無(wú)需創(chuàng)建單獨(dú)的.m文件。在腳本或函數(shù)內(nèi)部定義臨時(shí)使用的簡(jiǎn)單函數(shù)。fun函數(shù)的作用熱搜詞中出現(xiàn)了“fun函數(shù)的作用”。在MATLAB語(yǔ)境下fun通常不是一個(gè)特定的內(nèi)置函數(shù)而是一個(gè)占位符泛指“某個(gè)函數(shù)”。在很多函數(shù)的幫助文檔或示例中你會(huì)看到參數(shù)名稱為fun它期望接收一個(gè)函數(shù)句柄。例如fzero(fun, x0)尋找函數(shù)fun在x0附近的零點(diǎn)。integral(fun, a, b)對(duì)函數(shù)fun從a到b進(jìn)行數(shù)值積分。fplot(fun, [xmin, xmax])繪制函數(shù)fun在指定區(qū)間的圖形。 在這里fun可以是一個(gè)內(nèi)置函數(shù)的句柄如sin也可以是一個(gè)匿名函數(shù)如(x) x.^2 log(x)還可以是一個(gè)自定義函數(shù)的函數(shù)名需用引用如myFunction。5.2 回調(diào)函數(shù) (Callback Functions)實(shí)現(xiàn)交互的靈魂回調(diào)函數(shù)是MATLAB GUI編程和事件驅(qū)動(dòng)編程的核心概念。它不是一個(gè)具體的函數(shù)而是一種編程模式。什么是回調(diào)函數(shù)簡(jiǎn)單說(shuō)回調(diào)函數(shù)是一段代碼一個(gè)函數(shù)它被“注冊(cè)”給某個(gè)對(duì)象如圖形按鈕、定時(shí)器當(dāng)該對(duì)象觸發(fā)特定事件如按鈕被點(diǎn)擊、時(shí)間到達(dá)時(shí)這段代碼就會(huì)被自動(dòng)調(diào)用執(zhí)行。在圖形用戶界面 (GUI) 中的應(yīng)用這是回調(diào)函數(shù)最典型的應(yīng)用場(chǎng)景。無(wú)論是使用老式的GUIDE還是新的App Designer其本質(zhì)都是為界面組件按鈕、滑塊等設(shè)置回調(diào)函數(shù)。% 假設(shè)有一個(gè)按鈕其 Callback 屬性被設(shè)置為一個(gè)函數(shù)句柄 % 當(dāng)按鈕被按下時(shí)MATLAB會(huì)自動(dòng)調(diào)用這個(gè)函數(shù) button uicontrol(Style, pushbutton, String, Click Me, ... Callback, buttonPushed); % 回調(diào)函數(shù)的定義 function buttonPushed(src, event) disp(Button was pushed!); % 在這里執(zhí)行點(diǎn)擊按鈕后需要做的操作比如更新圖形、計(jì)算數(shù)據(jù)等 end回調(diào)函數(shù)通常接收兩個(gè)參數(shù)src觸發(fā)事件的源對(duì)象句柄和event事件數(shù)據(jù)對(duì)象盡管有時(shí)event可能為空。在課后習(xí)題中的體現(xiàn)入門課程的習(xí)題可能不會(huì)涉及完整的GUI編程但可能會(huì)通過(guò)簡(jiǎn)單的示例引入這個(gè)概念。例如講解timer對(duì)象時(shí)就需要為定時(shí)器設(shè)置TimerFcn定時(shí)器回調(diào)函數(shù)指定每隔一段時(shí)間要執(zhí)行什么操作。理解回調(diào)的關(guān)鍵被動(dòng)執(zhí)行回調(diào)函數(shù)不是你主動(dòng)在代碼流中調(diào)用的而是由系統(tǒng)在事件發(fā)生時(shí)“回調(diào)”的。函數(shù)句柄設(shè)置回調(diào)時(shí)傳遞的是函數(shù)的句柄如myCallback而不是函數(shù)調(diào)用的結(jié)果myCallback()。作用域回調(diào)函數(shù)在執(zhí)行時(shí)有其獨(dú)立的工作區(qū)。它如何訪問(wèn)主函數(shù)或其它函數(shù)中的變量這引出了 MATLAB 中共享數(shù)據(jù)的幾種方式使用app對(duì)象的屬性App Designer、使用UserData屬性、使用嵌套函數(shù)或顯式傳遞參數(shù)。6. 環(huán)境、路徑與函數(shù)識(shí)別問(wèn)題排查熱搜詞里反復(fù)出現(xiàn)“無(wú)法將‘XXX’項(xiàng)識(shí)別為 cmdlet、函數(shù)、腳本文件或可運(yùn)行程序的名稱”這類錯(cuò)誤。這雖然是Windows PowerShell的錯(cuò)誤信息格式但其反映的問(wèn)題本質(zhì)——“MATLAB找不到你調(diào)用的函數(shù)或命令”——是每個(gè)MATLAB用戶都會(huì)遇到的。6.1 錯(cuò)誤根源MATLAB路徑與當(dāng)前文件夾MATLAB執(zhí)行一個(gè)名稱如myfunc時(shí)會(huì)按特定順序在以下位置查找當(dāng)前工作區(qū)Workspace中的變量?jī)?yōu)先級(jí)最高所以不要用與重要函數(shù)同名的變量。當(dāng)前文件夾Current Folder下的.m文件、.mlx文件等。MATLAB搜索路徑Search Path中列出的所有文件夾。如果在這些地方都找不到就會(huì)報(bào)錯(cuò)“未定義函數(shù)或變量 ‘myfunc’”。課后習(xí)題常見(jiàn)場(chǎng)景你從網(wǎng)上下載或自己編寫了一個(gè)函數(shù)文件coolFunction.m并把它放在了D:\MyProjects文件夾。然后你打開(kāi)了MATLAB但當(dāng)前文件夾是C:\Users\YourName\Documents\MATLAB。此時(shí)在命令窗口輸入coolFunction()MATLAB就會(huì)報(bào)錯(cuò)因?yàn)樗辉贑:\Users\...這個(gè)文件夾里找而沒(méi)去D:\MyProjects找。6.2 解決方案正確設(shè)置路徑最直接的方法導(dǎo)航到文件所在文件夾在MATLAB的“當(dāng)前文件夾”工具欄或?yàn)g覽器中直接瀏覽并點(diǎn)擊進(jìn)入D:\MyProjects文件夾。這樣該文件夾下的所有函數(shù)文件就都可以被直接調(diào)用了。這是做習(xí)題時(shí)最推薦的方式一個(gè)項(xiàng)目一個(gè)文件夾所有相關(guān)文件放在一起操作前確保MATLAB的當(dāng)前文件夾就是這個(gè)項(xiàng)目文件夾。將文件夾添加到搜索路徑如果你的一些通用工具函數(shù)希望在任何項(xiàng)目中都能調(diào)用就需要將其所在文件夾添加到MATLAB的搜索路徑。臨時(shí)添加在命令窗口使用addpath(D:\MyProjects\MyUtilityFunctions)。這只在當(dāng)前MATLAB會(huì)話中有效關(guān)閉后失效。永久添加在MATLAB主頁(yè)選項(xiàng)卡的“環(huán)境”區(qū)域點(diǎn)擊“設(shè)置路徑”。在彈出的對(duì)話框中點(diǎn)擊“添加文件夾”或“添加并包含子文件夾”找到你的文件夾添加進(jìn)來(lái)然后點(diǎn)擊“保存”。這樣每次啟動(dòng)MATLAB這些文件夾都會(huì)被自動(dòng)搜索。使用絕對(duì)路徑或相對(duì)路徑調(diào)用你也可以不改變路徑直接在調(diào)用時(shí)指定函數(shù)的完整位置% 絕對(duì)路徑不推薦移植性差 result D:\MyProjects\coolFunction(input); % 相對(duì)路徑如果當(dāng)前文件夾是D:\MyProjects的父目錄 result .\MyProjects\coolFunction(input); % .\ 表示當(dāng)前目錄 result MyProjects\coolFunction(input); % 也可以避坑指南路徑?jīng)_突與陰影當(dāng)搜索路徑上有多個(gè)同名的函數(shù)時(shí)MATLAB會(huì)執(zhí)行它最先找到的那個(gè)。這可能導(dǎo)致你調(diào)用了一個(gè)舊版本或非預(yù)期的函數(shù)這種現(xiàn)象稱為“陰影Shadowing”。你可以使用which functionName命令來(lái)查看MATLAB實(shí)際找到的是哪個(gè)文件。在設(shè)置路徑時(shí)應(yīng)注意文件夾的上下順序或?qū)€(gè)人工具文件夾放在路徑列表靠前的位置。6.3 區(qū)分系統(tǒng)命令與MATLAB函數(shù)熱搜詞中的錯(cuò)誤信息源自PowerShell但MATLAB也有自己的系統(tǒng)調(diào)用命令!。例如!dir會(huì)在Windows上列出目錄。如果你在MATLAB中想調(diào)用一個(gè)外部程序比如一個(gè)Python腳本但該程序不在系統(tǒng)的環(huán)境變量PATH中你也會(huì)遇到類似“找不到”的錯(cuò)誤。這時(shí)你需要提供該外部程序的完整路徑或者先通過(guò)操作系統(tǒng)將其所在目錄添加到系統(tǒng)PATH環(huán)境變量中。7. 從入門到實(shí)踐構(gòu)建你的第一個(gè)函數(shù)集學(xué)習(xí)了這么多分散的函數(shù)后如何將它們串聯(lián)起來(lái)解決實(shí)際問(wèn)題課后習(xí)題的最終導(dǎo)向往往是引導(dǎo)你完成一個(gè)小型項(xiàng)目。這里我們以“數(shù)據(jù)處理與可視化”為例構(gòu)建一個(gè)簡(jiǎn)單的分析流程。7.1 場(chǎng)景設(shè)計(jì)分析一組實(shí)驗(yàn)數(shù)據(jù)假設(shè)我們有一組實(shí)驗(yàn)測(cè)量的數(shù)據(jù)存儲(chǔ)在data.xlsx文件中包含兩列Time和Voltage。我們的任務(wù)是讀取數(shù)據(jù)計(jì)算電壓的統(tǒng)計(jì)特征均值、標(biāo)準(zhǔn)差檢測(cè)異常值假設(shè)偏離均值3個(gè)標(biāo)準(zhǔn)差以上為異常繪制電壓隨時(shí)間變化的曲線并用不同顏色高亮異常點(diǎn)最后將結(jié)果圖表保存。7.2 分步實(shí)現(xiàn)與函數(shù)應(yīng)用步驟1讀取數(shù)據(jù)這里會(huì)用到可能拓展的函數(shù)如readtable或xlsread較老。我們使用更現(xiàn)代的readtable。data readtable(data.xlsx); % 讀取數(shù)據(jù)到表格 time data.Time; % 提取時(shí)間列 voltage data.Voltage; % 提取電壓列步驟2計(jì)算基本統(tǒng)計(jì)量使用mean,std函數(shù)。同時(shí)為了后續(xù)對(duì)比我們可能還需要median,min,max。v_mean mean(voltage); v_std std(voltage); fprintf(電壓均值: %.4f V, 標(biāo)準(zhǔn)差: %.4f V\n, v_mean, v_std);步驟3識(shí)別異常值運(yùn)用abs函數(shù)和邏輯索引。% 定義異常值閾值3倍標(biāo)準(zhǔn)差 threshold 3 * v_std; % 找出異常值的索引 is_outlier abs(voltage - v_mean) threshold; outlier_indices find(is_outlier); % find 函數(shù)將邏輯數(shù)組轉(zhuǎn)換為索引 outlier_times time(is_outlier); outlier_voltages voltage(is_outlier); fprintf(發(fā)現(xiàn) %d 個(gè)異常數(shù)據(jù)點(diǎn)。\n, sum(is_outlier));步驟4繪制圖形綜合運(yùn)用plot,hold on/off,scatter, RGB顏色xlabel,ylabel,title,legend以及xlim/ylim進(jìn)行定制。figure; % 創(chuàng)建新圖形窗口 % 繪制正常的電壓曲線使用細(xì)線、淺色 plot(time, voltage, -, Color, [0.7, 0.7, 0.7], LineWidth, 0.5, DisplayName, 正常數(shù)據(jù)); hold on; % 高亮繪制異常點(diǎn)使用醒目的紅色散點(diǎn) scatter(outlier_times, outlier_voltages, 80, r, filled, DisplayName, 異常點(diǎn)); hold off; % 添加標(biāo)簽和標(biāo)題 xlabel(時(shí)間 (s)); ylabel(電壓 (V)); title(實(shí)驗(yàn)電壓隨時(shí)間變化及異常點(diǎn)檢測(cè)); legend(Location, best); % 添加圖例 % 優(yōu)化坐標(biāo)軸范圍可以稍微留出一些邊距 x_range [min(time), max(time)]; y_range [min(voltage), max(voltage)]; x_margin (x_range(2) - x_range(1)) * 0.05; % 5%的邊距 y_margin (y_range(2) - y_range(1)) * 0.05; xlim([x_range(1)-x_margin, x_range(2)x_margin]); ylim([y_range(1)-y_margin, y_range(2)y_margin]); grid on; % 添加網(wǎng)格步驟5保存結(jié)果使用saveas或exportgraphicsR2020a以后推薦保存圖片并用movefile進(jìn)行歸檔。% 保存圖片 fig_filename voltage_analysis.png; exportgraphics(gcf, fig_filename, Resolution, 300); % 高分辨率保存 % 假設(shè)我們有一個(gè)‘results’文件夾將圖片移動(dòng)過(guò)去 results_dir results; if ~exist(results_dir, dir) mkdir(results_dir); % 如果文件夾不存在則創(chuàng)建 end movefile(fig_filename, fullfile(results_dir, fig_filename)); fprintf(分析圖表已保存至: %s\n, fullfile(results_dir, fig_filename));7.3 封裝為函數(shù)我們可以將上述流程封裝成一個(gè)函數(shù)analyze_voltage_data(filename)使其可以重復(fù)用于分析不同的數(shù)據(jù)文件。這就是從使用函數(shù)到創(chuàng)造函數(shù)的關(guān)鍵一步。function analyze_voltage_data(filename) % ANALYZE_VOLTAGE_DATA 分析電壓數(shù)據(jù)文件并生成報(bào)告圖表 % 輸入 % filename - 數(shù)據(jù)文件路徑如 data.xlsx % 輸出 % 在圖形窗口顯示圖表并在命令行打印統(tǒng)計(jì)信息。 % 步驟1-5的代碼放在這里... % ... (此處插入上述所有步驟的代碼但將硬編碼的 data.xlsx 替換為輸入?yún)?shù) filename) ... end通過(guò)這個(gè)完整的例子你將課后習(xí)題中拓展的abs,plot顏色控制、movefile等函數(shù)與數(shù)據(jù)讀取、邏輯索引、圖形標(biāo)注等基礎(chǔ)操作有機(jī)結(jié)合起來(lái)解決了一個(gè)完整的、有實(shí)際意義的問(wèn)題。這才是學(xué)習(xí)這些拓展函數(shù)的最終目的。