目錄
第9章:函數
9.1 使用 function 關鍵字來創建函數
9.1.1 函數的例子和功能
簡單輸出函數
計算兩個數的和與差
MATLAB內置函數調用
函數調用的特殊情況與靈活性
輸入參數的靈活性
輸出值的靈活性
查看內置函數源代碼
type 函數名(如type rgb2gray)
type 函數名.m(如type rgb2gray.m)
使用編輯器打開對應的.m文件
內置函數的優勢
9.1.2 函數的創建和運行
使用function關鍵字創建函數的語法
創建、保存和調用第一個自定義函數
創建步驟
示例
調用方法
形式參數和實際參數(形參和實參)
形式參數(形參)
實際參數(實參)
重要區別
函數工作的本質(基礎和函數工作區)
基礎工作區(Base Workspace)
函數工作區(Function Workspace)
工作區特點
使用斷點調試功能揭示函數的工作過程
斷點調試步驟
使用調試工具欄按鈕控制執行流程
調試示例
在自定義函數中調用另一個自定義函數
return關鍵字:將控制權交還給調用腳本或函數
使用場景
示例
使用global關鍵字聲明全局變量
語法
使用規則
示例
使用persistent關鍵字聲明持久變量
語法
特點
示例
常見錯誤場景
函數名與文件名不匹配
函數路徑問題
輸入輸出參數數量不匹配
變量作用域混淆
函數遞歸調用導致棧溢出
使用dbstop if error進行錯誤調試
基本用法
調試流程
示例
9.1.3 函數的高級用法
函數高級用法總結表
實時函數
局部函數
示例
嵌套函數
示例
可變數量的輸入參數或輸出值
nargin和nargout
Varargin
Varargout
narginchk和nargoutchk
arguments代碼塊
遞歸函數
示例(計算階乘)
第9章:函數
9.1 使用 function 關鍵字來創建函數
在數學中,函數是一種將輸入值映射到輸出值的關系;
在計算機中,函數是一段可重復使用的代碼塊,用于執行特定任務并返回結果。
函數的主要作用是提高代碼的模塊化程度、減少重復代碼、增強程序的可讀性和可維護性。
9.1.1 函數的例子和功能
函數類別 | 函數名 | 功能描述 |
數學運算 | abs(z) | 求復數z的模,或字符串轉ASCII值 |
數學運算 | factorial(n) | 計算n的階乘 |
數學運算 | nchoosek(n,k) | 計算組合數C(n,k) |
邏輯判斷 | all(A) | 若向量A的所有元素非零則結果為1 |
方程求解 | solve | 求解方程,得到全部符號解 |
方程求解 | vpasolve | 求解方程的數值近似解 |
方程求解 | fsolve | 求解非線性方程組 |
方程求解 | fzero | 求解一維函數的零點 |
方程求解 | roots | 求解多項式的根 |
簡單輸出函數
function hello()disp('Hello, MATLAB!');end
可以直接調用:hello()
計算兩個數的和與差
function [sum, diff] = calculate(a, b)sum = a + b;diff = a - b;end
調用方式:[s, d] = calculate(10, 5)
MATLAB內置函數調用
MATLAB提供了豐富的內置函數,可以直接調用使用。
例如:
- abs(z): 求復數z的模,也可將字符串轉化為ASCII值
- all(A): 若向量A的所有元素非零則結果為1
- nchoosek(n,k): 求組合數C(n,k)
- factorial(n): 求n的階乘
函數調用的特殊情況與靈活性
輸入參數的靈活性
- 可以定義具有默認值的參數
- 可以使用varargin處理可變數量的輸入參數
- 可以根據輸入參數的類型和數量執行不同的操作
輸出值的靈活性
- 函數可以有多個輸出值,如[sum, diff] = calculate(a, b)
- 如果調用函數時不指定輸出變量,結果將存儲在默認變量ans中
- 可以使用varargout處理可變數量的輸出參數
查看內置函數源代碼
type 函數名(如type rgb2gray)
type 函數名.m(如type rgb2gray.m)
使用編輯器打開對應的.m文件
內置函數的優勢
- 經過優化,執行效率高
- 代碼經過嚴格測試,可靠性高
- 提供了豐富的功能,覆蓋科學計算的各個方面
- 與MATLAB環境無縫集成,使用方便
9.1.2 函數的創建和運行
知識點 | 語法/方法 | 說明 | 示例 |
函數定義 | function [輸出] = 函數名(輸入) | 使用function關鍵字定義函數 | function area = circleArea(r) |
函數調用 | 變量 = 函數名(參數) | 調用已定義的函數 | a = circleArea(5); |
形參和實參 | - | 形參是函數定義中的參數,實參是調用時傳入的值 | function area = circleArea(radius)中radius是形參,circleArea(5)中5是實參 |
斷點設置 | 點擊行號左側或使用dbstop | 在代碼中設置斷點進行調試 | dbstop in circleArea at 3 |
return語句 | return | 提前終止函數執行 | if x < 0; return; end |
全局變量 | global 變量名 | 聲明可在多個函數間共享的變量 | global counter; |
持久變量 | persistent 變量名 | 聲明在函數調用間保持值的變量 | persistent callCount; |
錯誤調試 | dbstop if error | 在錯誤發生時自動進入調試模式 | dbstop if error |
使用function關鍵字創建函數的語法
function [輸出參數1, 輸出參數2, ...] = 函數名(輸入參數1, 輸入參數2, ...)% 函數說明注釋% 函數體% 執行特定任務的代碼end
創建、保存和調用第一個自定義函數
創建步驟
- 在MATLAB編輯器中新建一個.m文件
- 使用function關鍵字定義函數
- 將文件保存為與函數名相同的名稱(例如函數名為myFunction,則文件應保存為myFunction.m)
示例
創建一個計算圓面積的函數
function area = circleArea(radius)% 計算圓的面積% 輸入:radius - 圓的半徑% 輸出:area - 圓的面積area = pi * radius^2;end
調用方法
% 在命令窗口或其他腳本中調用r = 5;a = circleArea(r);? % a將得到圓的面積disp(['半徑為', num2str(r), '的圓的面積是:', num2str(a)]);
形式參數和實際參數(形參和實參)
形式參數(形參)
函數定義中使用的參數,如上面例子中的radius
實際參數(實參)
調用函數時傳入的實際值,如上面例子中的r
重要區別
- 形參只在函數內部有效,是函數的局部變量
- 實參是調用函數時提供的具體值或變量
- 函數調用時,實參的值會傳遞給對應的形參
函數工作的本質(基礎和函數工作區)
基礎工作區(Base Workspace)
MATLAB命令行和腳本所在的工作區
函數工作區(Function Workspace)
每個函數獨立的工作區
工作區特點
- 函數工作區與基礎工作區是隔離的
- 函數內部定義的變量只在函數內部有效
- 函數不能直接訪問其他工作區的變量(除非使用global或persistent關鍵字)
- 函數調用結束后,其工作區中的變量會被銷毀
使用斷點調試功能揭示函數的工作過程
斷點調試步驟
- 在MATLAB編輯器中,點擊代碼行號左側設置斷點(紅色圓點)
- 運行函數
- 程序執行到斷點處會暫停
使用調試工具欄按鈕控制執行流程
- Continue:繼續執行到下一個斷點或程序結束
- Step:單步執行(進入函數)
- Step In:進入函數內部
- Step Out:跳出當前函數
調試示例
function [sum, product] = calculate(a, b)% 設置斷點在這一行sum = a + b;????? % 斷點1product = a * b;? % 斷點2end
通過斷點可以觀察變量值的變化,理解函數執行過程。
在自定義函數中調用另一個自定義函數
function result = computeStatistics(data)% 主函數:計算數據的統計信息% 調用其他自定義函數avg = calculateAverage(data);med = calculateMedian(data);result = struct('average', avg, 'median', med);endfunction avg = calculateAverage(data)% 計算平均值avg = sum(data) / length(data);endfunction med = calculateMedian(data)% 計算中位數sortedData = sort(data);n = length(sortedData);if mod(n, 2) == 0med = (sortedData(n/2) + sortedData(n/2 + 1)) / 2;elsemed = sortedData((n + 1) / 2);endend
return關鍵字:將控制權交還給調用腳本或函數
return關鍵字用于提前終止函數執行,并將控制權返回給調用者。
使用場景
- 滿足特定條件時提前退出函數
- 錯誤處理
示例
function result = checkPositive(num)% 檢查數字是否為正數if num <= 0disp('輸入不是正數');result = [];return;? % 提前退出函數endresult = num;disp(['輸入是正數: ', num2str(num)]);end
使用global關鍵字聲明全局變量
全局變量可以在多個函數和基礎工作區之間共享。
語法
global 變量名1 變量名2 ...
使用規則
- 在每個需要訪問全局變量的函數中,都必須使用global關鍵字聲明
- 全局變量在程序運行期間一直存在
- 應謹慎使用全局變量,以免造成代碼混亂
示例
function setGlobalValue(value)global globalVar;? % 聲明全局變量globalVar = value;endfunction displayGlobalValue()global globalVar;? % 聲明全局變量disp(['全局變量的值是: ', num2str(globalVar)]);end% 在命令窗口中setGlobalValue(42);displayGlobalValue();? % 顯示: 全局變量的值是: 42
使用persistent關鍵字聲明持久變量
持久變量類似于其他編程語言中的靜態變量,它們在函數調用之間保持其值。
語法
persistent 變量名1 變量名2 ...
特點
- 持久變量只在聲明它的函數內部可見
- 函數調用結束后,持久變量的值不會被清除
- 當MATLAB會話結束或清除函數時,持久變量才會被清除
- 持久變量只在第一次調用函數時初始化
示例
function counter = callCounter()persistent count;? % 聲明持久變量% 第一次調用時初始化if isempty(count)count = 0;endcount = count + 1;counter = count;disp(['函數已調用次數: ', num2str(counter)]);end% 在命令窗口中多次調用callCounter();? % 顯示: 函數已調用次數: 1callCounter();? % 顯示: 函數已調用次數: 2callCounter();? % 顯示: 函數已調用次數: 3
常見錯誤場景
函數名與文件名不匹配
錯誤:函數名為calculateArea,但文件保存為area.m
解決:確保文件名與函數名完全一致
函數路徑問題
錯誤:函數文件不在MATLAB的搜索路徑中
解決:使用addpath添加路徑或將文件放在當前工作目錄
輸入輸出參數數量不匹配
錯誤:函數定義需要2個輸出參數,但調用時只提供1個
解決:檢查函數定義和調用語句
變量作用域混淆
錯誤:試圖在函數外部訪問函數內部變量
解決:使用適當的參數傳遞或全局變量
函數遞歸調用導致棧溢出
錯誤:無限遞歸調用
解決:確保遞歸有終止條件
使用dbstop if error進行錯誤調試
dbstop if error是MATLAB中強大的調試工具,它可以在發生錯誤時自動暫停程序執行,進入調試模式。
基本用法
dbstop if error? % 在任何錯誤發生時停止dbstop if caught error? % 在被try-catch捕獲的錯誤處停止dbstop if warning? % 在警告發生時停止dbstop if naninf? % 在NaN或Inf值產生時停止dbstop if error -identifier 特定錯誤ID? % 只在特定錯誤發生時停止
調試流程
- 在命令窗口輸入dbstop if error
- 運行可能導致錯誤的代碼
- 當錯誤發生時,MATLAB會自動暫停并進入調試模式
- 檢查變量值,分析錯誤原因
- 使用調試命令逐步執行代碼
- 找到并修復錯誤后,使用dbclear all清除所有斷點
示例
% 假設有以下函數function result = divideNumbers(a, b)result = a / b;end% 在命令窗口中dbstop if error? % 設置錯誤斷點divideNumbers(10, 0);? % 這將導致除以零錯誤,程序會自動暫停
當錯誤發生時,可以檢查K>>提示符下的變量值,理解錯誤原因。
9.1.3 函數的高級用法
函數高級用法總結表
功能類型 | 說明 | 語法示例 | 特點 |
實時函數 | 用于實時數據分析的函數 | function output = realTimeFunction(input) | 可實時處理數據并即時輸出結果 |
局部函數 | 同一文件中的輔助函數 | function output = localFunction(input) | 只能被同一文件中的其他函數調用 |
嵌套函數 | 定義在函數內部的函數 | function parentFunction | 可訪問父函數工作區中的變量 |
可變輸入參數 | 接受任意數量輸入的函數 | function output = varArgFunction(varargin) | 使用varargin收集所有輸入參數 |
可變輸出參數 | 返回任意數量輸出的函數 | function varargout = varOutFunction(input) | 使用varargout返回多個輸出 |
參數驗證 | 驗證和限制函數參數 | arguments | 自R2019b起支持,可設置參數類型、大小和約束 |
遞歸函數 | 調用自身的函數 | function result = fact(n) | 需要明確的停止條件 |
實時函數
實時函數是MATLAB中用于實現實時數據分析的工具,能夠在程序運行過程中不斷接收輸入數據并即時輸出結果,非常適用于需要實時更新的應用場景,如數據采集、信號處理等。
實時函數的創建與普通函數類似,但具有實時數據處理能力,可以在實時腳本中使用,提供動態更新的可視化效果。
局部函數
在MATLAB中,一個函數文件可以包含多個函數,其中第一個函數稱為主函數,其他函數稱為局部函數。
主函數可以被外部調用,而局部函數只能被同一文件中的其他函數調用,無法直接被外部調用。
示例
function mainFunction()% 主函數result = localFunction(5);disp(result);endfunction output = localFunction(input)% 局部函數output = input * 2;end
嵌套函數
嵌套函數是完全包含在父函數內部的函數,可以出現在函數體內的任何位置,以function聲明,以end結束。
嵌套函數可以訪問父函數工作區中的變量,這是它與局部函數的主要區別。
示例
function parentFunctionx = 10;function nestedFunction% 可以訪問父函數的變量xdisp(['x的值是: ', num2str(x)]);endnestedFunction();end
可變數量的輸入參數或輸出值
nargin和nargout
用于獲取函數輸入和輸出參數的數目
Varargin
可變長度輸入參數列表,允許函數接受任意數量的輸入參數
Varargout
可變長度的輸出參數列表,允許函數返回任意數量的輸出值
narginchk和nargoutchk
用于驗證輸入和輸出參數數目
示例
function varargout = flexibleFunction(varargin)% 輸入參數數量numInputs = nargin;disp(['輸入參數數量: ', num2str(numInputs)]);% 處理輸入參數for i = 1:numInputsdisp(['第', num2str(i), '個參數: ', num2str(varargin{i})]);end% 根據輸入參數數量決定輸出參數數量if nargout == 0% 無輸出return;elseif nargout == 1% 單個輸出varargout{1} = sum(cell2mat(varargin));else% 多個輸出for i = 1:nargoutif i <= numInputsvarargout{i} = varargin{i} * 2;elsevarargout{i} = 0;endendendend
arguments代碼塊
參數聲明或驗證
自R2019b版本起,MATLAB引入了arguments代碼塊,用于函數參數的聲明和驗證。arguments對象表示函數的實參集合,僅在函數體內可見,并可以直接訪問。
示例
function validatedFunction(x, y)argumentsx (1,1) double {mustBePositive, mustBeInteger} = 10;y (1,:) string = "default";end% 函數體disp(['x的值: ', num2str(x)]);disp(['y的值: ', y]);end
遞歸函數
遞歸是指在函數體內調用自身的編程技術。
在MATLAB中,遞歸函數的定義與其他編程語言類似,需要明確定義停止條件,否則可能導致無限遞歸和棧溢出。
示例(計算階乘)
function result = factorial(n)% 停止條件if n == 0 || n == 1result = 1;else% 遞歸調用result = n * factorial(n-1);endend