matlab 教程
MATLAB(Matrix Laboratory)是一个高性能的数值计算环境和编程语言,专为工程计算、数据分析和算法开发设计。2. 基本语法与数据类型2.1 语法规则2.2 变量命名规则2.3 数据类型详解2.3.1 数值类型2.3.2 逻辑类型2.3.3 字符和字符串2.4 类型转换3. 数组和矩阵操作3.1 数组创建3.1.1 直接创建3.1.2 使用函数创建3.1.3 序列创建3.2 数组索
·
文章目录
-
- 1. MATLAB简介与环境
- 2. 基本语法与数据类型
- 3. 数组和矩阵操作
- 4. 运算符详解
- 5. 控制结构
- 6. 函数编程
- 6.2 高级函数特性
- 7. 数据输入输出
- 8. 绘图与可视化
- 9. 字符串处理
- 10. 结构体与元胞数组
- 11. 文件操作
- 12. 调试与错误处理
- 13. 性能优化
- 14. 工具箱简介
- 15. 实战项目
- 16. 常见问题与解决方案
1. MATLAB简介与环境
1.1 什么是MATLAB
MATLAB(Matrix Laboratory)是一个高性能的数值计算环境和编程语言,专为工程计算、数据分析和算法开发设计。
1.2 与Python/C++的对比
特性 | Python | C/C++ | MATLAB |
---|---|---|---|
类型 | 解释型 | 编译型 | 解释型 |
主要用途 | 通用编程 | 系统编程 | 数值计算 |
矩阵运算 | 需要NumPy | 需要库 | 内置支持 |
学习曲线 | 平缓 | 陡峭 | 中等 |
执行速度 | 中等 | 最快 | 快(矩阵运算) |
1.3 MATLAB环境
- 命令窗口(Command Window): 交互式执行命令
- 编辑器(Editor): 编写和编辑脚本、函数
- 工作区(Workspace): 查看变量
- 命令历史(Command History): 查看历史命令
- 当前文件夹(Current Folder): 文件管理
1.4 基本操作命令
% 基本环境命令
clc % 清除命令窗口
clear % 清除工作区所有变量
clear var % 清除指定变量
close all % 关闭所有图形窗口
who % 显示当前变量列表
whos % 详细显示变量信息
pwd % 显示当前路径
cd % 改变当前路径
ls % 列出当前目录文件
2. 基本语法与数据类型
2.1 语法规则
% 注释:单行注释用%,多行注释用%{ %}
% 这是单行注释
%{
这是多行注释
可以写很多行
%}
% 语句结束:
a = 5; % 分号抑制输出
b = 3 % 不加分号会显示结果
% 续行:使用...
long_variable_name = 1 + 2 + 3 + ...
4 + 5 + 6;
2.2 变量命名规则
% 命名规则:
% 1. 以字母开头
% 2. 只能包含字母、数字、下划线
% 3. 区分大小写
% 4. 不能使用关键字
% 有效的变量名
var1 = 10;
my_variable = 20;
MyVariable = 30;
variable_2023 = 40;
% 无效的变量名(会报错)
% 2var = 10; % 以数字开头
% my-var = 20; % 包含连字符
% for = 30; % 使用关键字
2.3 数据类型详解
2.3.1 数值类型
% 双精度浮点数(默认)
a = 3.14159;
b = 1.23e-4; % 科学记数法
c = 1.23e4;
% 整数类型
int8_var = int8(127); % 8位有符号整数
uint8_var = uint8(255); % 8位无符号整数
int16_var = int16(32767); % 16位有符号整数
uint16_var = uint16(65535); % 16位无符号整数
int32_var = int32(2147483647); % 32位有符号整数
uint32_var = uint32(4294967295); % 32位无符号整数
int64_var = int64(9223372036854775807); % 64位有符号整数
% 单精度浮点数
single_var = single(3.14159);
% 复数
complex_var = 3 + 4i; % 或 3 + 4*i
complex_var2 = complex(3, 4);
2.3.2 逻辑类型
% 布尔值
bool_true = true;
bool_false = false;
% 逻辑运算结果
result = (5 > 3); % true
result2 = (2 == 3); % false
% 逻辑数组
logical_array = [true, false, true];
2.3.3 字符和字符串
% 字符数组(传统方式)
char_var = 'Hello';
char_array = ['Hello'; 'World']; % 注意:每行长度必须相同
% 字符串数组(R2016b及以后)
str_var = "Hello";
str_array = ["Hello", "World", "MATLAB"];
% 字符串与字符数组的区别
char_example = 'Hello'; % 1x5 char
string_example = "Hello"; % 1x1 string
2.4 类型转换
% 数值转换
a = 3.14;
b = int32(a); % 转换为32位整数
c = single(a); % 转换为单精度
d = char(65); % ASCII转字符: 'A'
% 字符串转换
num_str = '123';
num_val = str2double(num_str); % 字符串转数值
num_val2 = str2num(num_str); % 字符串转数值(可处理向量)
% 数值转字符串
val = 3.14159;
str_val = num2str(val); % 数值转字符串
str_val2 = sprintf('%.2f', val); % 格式化转换
3. 数组和矩阵操作
3.1 数组创建
3.1.1 直接创建
% 行向量
row_vector = [1, 2, 3, 4, 5];
row_vector2 = [1 2 3 4 5]; % 逗号可省略
% 列向量
col_vector = [1; 2; 3; 4; 5];
% 矩阵
matrix = [1, 2, 3; 4, 5, 6; 7, 8, 9];
matrix2 = [1 2 3
4 5 6
7 8 9]; % 分行写法
3.1.2 使用函数创建
% 特殊矩阵
zeros_matrix = zeros(3, 4); % 3x4零矩阵
ones_matrix = ones(2, 5); % 2x5全1矩阵
eye_matrix = eye(4); % 4x4单位矩阵
diag_matrix = diag([1,2,3,4]); % 对角矩阵
% 随机矩阵
rand_matrix = rand(3, 3); % 3x3均匀分布随机矩阵[0,1]
randn_matrix = randn(2, 4); % 2x4标准正态分布随机矩阵
randi_matrix = randi(10, 3, 3); % 3x3随机整数矩阵[1,10]
randi_matrix2 = randi([5,15], 2, 3); % 2x3随机整数矩阵[5,15]
3.1.3 序列创建
% 等差数列
seq1 = 1:5; % [1 2 3 4 5]
seq2 = 1:2:10; % [1 3 5 7 9],步长为2
seq3 = 10:-1:1; % [10 9 8 7 6 5 4 3 2 1],递减
% 等间距数列
linspace_seq = linspace(0, 10, 5); % 0到10等分5个点
logspace_seq = logspace(1, 3, 5); % 10^1到10^3等分5个点(对数空间)
% 重复数组
repmat_array = repmat([1, 2], 3, 2); % 重复[1,2] 3行2列
3.2 数组索引与切片
3.2.1 基本索引(注意:MATLAB索引从1开始!)
A = [1, 2, 3; 4, 5, 6; 7, 8, 9];
% 单个元素
element = A(2, 3); % 第2行第3列:6
element2 = A(1, 1); % 第1行第1列:1
% 线性索引(按列优先)
linear_element = A(5); % 第5个元素:5
linear_element2 = A(end); % 最后一个元素:9
% 使用end关键字
last_element = A(end, end); % 最后一行最后一列:9
second_last = A(end-1, end); % 倒数第二行最后一列:6
3.2.2 切片操作
A = [1, 2, 3, 4; 5, 6, 7, 8; 9, 10, 11, 12];
% 行切片
first_row = A(1, :); % 第1行所有列:[1 2 3 4]
last_row = A(end, :); % 最后一行:[9 10 11 12]
% 列切片
first_col = A(:, 1); % 所有行第1列:[1; 5; 9]
last_col = A(:, end); % 最后一列:[4; 8; 12]
% 子矩阵
sub_matrix = A(1:2, 2:3); % 第1-2行,第2-3列:[2 3; 6 7]
sub_matrix2 = A([1,3], [2,4]); % 第1,3行,第2,4列:[2 4; 10 12]
% 所有元素
all_elements = A(:); % 所有元素(列向量)
特性 | MATLAB | NumPy (Python) |
---|---|---|
索引起始 | 从1开始 | 从0开始 |
语法 | 圆括号 A(行, 列) |
方括号 A[行, 列] |
第一个元素 | A(1, 1) |
A[0, 0] |
范围索引 | A(1:3, 1:2) |
A[0:3, 0:2] |
间隔索引 | A([1:3], [1:2]) |
A[[0:3], [0:2]] |
逆向 | end:-1:1 |
::-1 |
所有行/列 | A(:, 2) |
A[:, 1] |
最后一个元素 | A(end, end) |
A[-1, -1] |
3.2.3 逻辑索引
A = [1, -2, 3; -4, 5, -6; 7, -8, 9];
% 逻辑条件
positive_mask = A > 0; % 逻辑矩阵
positive_elements = A(A > 0); % 提取正数:[1; 3; 5; 7; 9]
% 复合条件
condition = (A > 0) & (A < 8); % 大于0且小于8
selected = A(condition); % [1; 3; 5; 7]
% 替换元素
A(A < 0) = 0; % 将负数替换为0
3.3 数组操作
3.3.1 数组拼接
% 水平拼接
A = [1, 2; 3, 4];
B = [5, 6; 7, 8];
C_horizontal = [A, B]; % [1 2 5 6; 3 4 7 8]
C_horizontal2 = horzcat(A, B); % 同上
% 垂直拼接
C_vertical = [A; B]; % [1 2; 3 4; 5 6; 7 8]
C_vertical2 = vertcat(A, B); % 同上
% 高维拼接
C_3d = cat(3, A, B); % 沿第3维拼接
3.3.2 数组重塑
A = [1, 2, 3, 4, 5, 6];
% 重塑形状
B = reshape(A, 2, 3); % 重塑为2x3:[1 3 5; 2 4 6]
C = reshape(A, 3, 2); % 重塑为3x2:[1 4; 2 5; 3 6]
% 转置
A_matrix = [1, 2, 3; 4, 5, 6];
A_transpose = A_matrix'; % 转置:[1 4; 2 5; 3 6]
A_transpose2 = transpose(A_matrix); % 同上
% 复数矩阵的共轭转置
complex_matrix = [1+2i, 3-4i; 5+6i, 7-8i];
conjugate_transpose = complex_matrix'; % 共轭转置
transpose_only = complex_matrix.'; % 仅转置(不共轭)
3.3.3 数组排序
% 向量排序
vec = [3, 1, 4, 1, 5, 9];
sorted_vec = sort(vec); % 升序:[1 1 3 4 5 9]
sorted_desc = sort(vec, 'descend'); % 降序:[9 5 4 3 1 1]
% 获取排序索引
[sorted_vec, indices] = sort(vec);
% sorted_vec = [1 1 3 4 5 9]
% indices = [2 4 1 3 5 6]
% 矩阵排序
matrix = [3, 1, 4; 1, 5, 9; 2, 6, 5];
sorted_matrix = sort(matrix); % 按列排序
sorted_matrix2 = sort(matrix, 2); % 按行排序
4. 运算符详解
4.1 算术运算符
4.1.1 标量运算
% 基本运算
a = 10; b = 3;
addition = a + b; % 加法:13
subtraction = a - b; % 减法:7
multiplication = a * b; % 乘法:30
division = a / b; % 除法:3.3333
power = a ^ b; % 幂运算:1000
modulo = mod(a, b); % 取模:1
4.1.2 矩阵运算
A = [1, 2; 3, 4];
B = [5, 6; 7, 8];
scalar = 2;
% 矩阵加减法
C = A + B; % 矩阵加法:[6 8; 10 12]
D = A - B; % 矩阵减法:[-4 -4; -4 -4]
% 矩阵乘法
E = A * B; % 矩阵乘法:[19 22; 43 50]
F = A * scalar; % 标量乘法:[2 4; 6 8]
% 矩阵除法
G = A / B; % 右除:A * inv(B)
H = A \ B; % 左除:inv(A) * B
% 矩阵幂运算
I = A ^ 2; % 矩阵幂:A * A
4.1.3 逐元素运算(重要!)
A = [1, 2; 3, 4];
B = [5, 6; 7, 8];
% 逐元素运算(注意点号)
C = A .* B; % 逐元素乘法:[5 12; 21 32]
D = A ./ B; % 逐元素除法:[0.2 0.333; 0.429 0.5]
E = A .^ 2; % 逐元素平方:[1 4; 9 16]
F = A .^ B; % 逐元素幂运算:[1 64; 2187 65536]
% 逐元素函数
G = sqrt(A); % 逐元素开方
H = sin(A); % 逐元素正弦
I = exp(A); % 逐元素指数
4.2 比较运算符
a = 5; b = 3;
A = [1, 2, 3; 4, 5, 6];
B = [1, 0, 4; 4, 5, 0];
% 标量比较
result1 = a > b; % true
result2 = a == b; % false
result3 = a ~= b; % true(注意:不是!=)
result4 = a <= b; % false
% 矩阵比较(逐元素)
C = A > B; % [false true false; false false true]
D = A == B; % [true false false; true true false]
E = A ~= B; % [false true true; false false true]
% 矩阵比较函数
is_equal = isequal(A, B); % false(整体比较)
is_close = all(abs(A-B) < 1e-10, 'all'); % 近似相等判断
4.3 逻辑运算符
% 逻辑运算符
a = true; b = false;
result1 = a && b; % 逻辑与(短路):false
result2 = a || b; % 逻辑或(短路):true
result3 = ~a; % 逻辑非:false
% 数组逻辑运算符
A = [true, false; true, true];
B = [false, true; true, false];
C = A & B; % 逐元素与:[false false; true false]
D = A | B; % 逐元素或:[true true; true true]
E = ~A; % 逐元素非:[false true; false false]
% 逻辑函数
result_any = any(A); % 任意元素为真:[true true]
result_all = all(A); % 所有元素为真:[true false]
result_any_all = any(A, 'all'); % 任意元素为真:true
result_all_all = all(A, 'all'); % 所有元素为真:false
4.4 位运算符
% 位运算
a = 5; % 二进制:101
b = 3; % 二进制:011
bit_and = bitand(a, b); % 位与:1
bit_or = bitor(a, b); % 位或:7
bit_xor = bitxor(a, b); % 位异或:6
bit_not = bitcmp(a, 8); % 位非(8位):250
bit_shift_left = bitshift(a, 2); % 左移2位:20
bit_shift_right = bitshift(a, -1); % 右移1位:2
5. 控制结构
5.1 条件语句
5.1.1 if-else语句
% 基本if语句
x = 10;
if x > 5
disp('x大于5');
end
% if-else语句
x = 3;
if x > 5
disp('x大于5');
else
disp('x不大于5');
end
% if-elseif-else语句
score = 85;
if score >= 90
grade = 'A';
elseif score >= 80
grade = 'B';
elseif score >= 70
grade = 'C';
elseif score >= 60
grade = 'D';
else
grade = 'F';
end
fprintf('成绩等级: %s\n', grade);
% 复合条件
age = 25;
income = 50000;
if age >= 18 && income > 30000
disp('符合贷款条件');
elseif age >= 18 || income > 100000
disp('需要进一步评估');
else
disp('不符合贷款条件');
end
5.1.2 switch-case语句
% 基本switch语句
day = 3;
switch day
case 1
day_name = '周一';
case 2
day_name = '周二';
case 3
day_name = '周三';
case 4
day_name = '周四';
case 5
day_name = '周五';
case {6, 7} % 多个case值
day_name = '周末';
otherwise
day_name = '无效日期';
end
fprintf('今天是%s\n', day_name);
% 字符串switch
operation = 'add';
a = 10; b = 5;
switch operation
case 'add'
result = a + b;
case 'subtract'
result = a - b;
case 'multiply'
result = a * b;
case 'divide'
if b ~= 0
result = a / b;
else
result = NaN;
end
otherwise
result = NaN;
end
5.2 循环结构
5.2.1 for循环
% 基本for循环
for i = 1:5
fprintf('i = %d\n', i);
end
% 步长循环
for i = 1:2:10
fprintf('i = %d\n', i); % 输出1, 3, 5, 7, 9
end
% 递减循环
for i = 10:-1:1
fprintf('i = %d\n', i);
end
% 遍历数组
numbers = [2, 4, 6, 8, 10];
for num = numbers
fprintf('数字: %d\n', num);
end
% 嵌套循环
for i = 1:3
for j = 1:3
fprintf('(%d, %d) ', i, j);
end
fprintf('\n');
end
% 矩阵循环
A = [1, 2, 3; 4, 5, 6];
for i = 1:size(A, 1) % 遍历行
for j = 1:size(A, 2) % 遍历列
fprintf('A(%d,%d) = %d\n', i, j, A(i,j));
end
end
5.2.2 while循环
% 基本while循环
i = 1;
while i <= 5
fprintf('i = %d\n', i);
i = i + 1;
end
% 条件循环
sum_val = 0;
i = 1;
while sum_val < 100
sum_val = sum_val + i;
i = i + 1;
end
fprintf('和为%d时,i = %d\n', sum_val, i-1);
% 无限循环(需要break跳出)
counter = 0;
while true
counter = counter + 1;
if counter > 10
break;
end
fprintf('计数器: %d\n', counter);
end
5.2.3 循环控制语句
% break语句
for i = 1:10
if i == 5
break; % 跳出循环
end
fprintf('i = %d\n', i);
end
% continue语句
for i = 1:10
if mod(i, 2) == 0
continue; % 跳过偶数
end
fprintf('奇数: %d\n', i);
end
% 嵌套循环中的break
for i = 1:3
for j = 1:3
if i == 2 && j == 2
break; % 只跳出内层循环
end
fprintf('(%d, %d) ', i, j);
end
fprintf('\n');
end
5.3 异常处理
% try-catch语句
try
a = 10;
b = 0;
result = a / b; % 这会产生Inf,不是错误
% 故意产生错误
matrix = [1, 2; 3, 4];
value = matrix(5, 5); % 索引越界
catch ME
fprintf('捕获到错误: %s\n', ME.message);
fprintf('错误标识符: %s\n', ME.identifier);
fprintf('错误位置: %s, 行%d\n', ME.stack(1).name, ME.stack(1).line);
% 处理错误
result = NaN;
end
% 完整的try-catch-end结构
filename = 'nonexistent.txt';
try
data = load(filename);
fprintf('文件加载成功\n');
catch ME
if strcmp(ME.identifier, 'MATLAB:load:couldNotReadFile')
fprintf('文件不存在: %s\n', filename);
data = [];
else
fprintf('未知错误: %s\n', ME.message);
rethrow(ME); % 重新抛出错误
end
end
6. 函数编程
6.1 函数基础
6.1.1 函数定义
% 基本函数定义(保存为separate .m文件)
function result = square(x)
% SQUARE 计算输入的平方
% 输入: x - 数值或数组
% 输出: result - x的平方
result = x .^ 2;
end
% 多输入参数函数
function result = add_numbers(a, b, c)
% 计算三个数的和
result = a + b + c;
end
% 多输出参数函数
function [sum_val, diff_val, prod_val] = calculate(a, b)
% 计算两数的和、差、积
sum_val = a + b;
diff_val = a - b;
prod_val = a * b;
end
% 可变参数函数
function result = sum_all(varargin)
% 计算所有输入参数的和
result = 0;
for i = 1:nargin
result = result + varargin{i};
end
end
6.1.2 函数调用
% 调用基本函数
x = 5;
y = square(x); % y = 25
% 调用多参数函数
result = add_numbers(1, 2, 3); % result = 6
% 调用多输出函数
[s, d, p] = calculate(10, 5); % s=15, d=5, p=50
s_only = calculate(10, 5); % 只获取第一个输出
% 调用可变参数函数
total = sum_all(1, 2, 3, 4, 5); % total = 15
6.2 高级函数特性
6.2.1 默认参数和参数检查
% 使用inputParser进行参数解析
function result = advanced_function(data, varargin)
% 高级函数示例,演示参数解析
% 创建输入解析器
p = inputParser;
% 必需参数
addRequired(p, 'data', @isnumeric);
% 可选参数
addOptional(p, 'method', 'mean', @(x) any(validatestring(x, {'mean', 'median', 'sum'})));
% 名称-值对参数
addParameter(p, 'normalize', false, @islogical);
addParameter(p, 'precision', 2, @(x) isnumeric(x) && x > 0);
% 解析输入
parse(p, data, varargin{:});
% 提取参数
method = p.Results.method;
normalize = p.Results.normalize;
precision = p.Results.precision;
% 数据预处理
if normalize
data = data / max(data);
end
% 根据方法计算结果
switch method
case 'mean'
result = mean(data);
case 'median'
result = median(data);
case 'sum'
result = sum(data);
end
% 精度控制
result = round(result, precision);
end
% 调用示例
data = [1, 2, 3, 4, 5];
result1 = advanced_function(data); % 使用默认参数
result2 = advanced_function(data, 'median'); % 指定方法
result3 = advanced_function(data, 'sum', 'normalize', true); % 使用名称-值对
6.2.2 嵌套函数和子函数
% 嵌套函数示例
function main_function()
% 主函数
x = 10;
y = 5;
% 调用嵌套函数
result = nested_calculation();
fprintf('结果: %d\n', result);
% 嵌套函数可以访问主函数的变量
function output = nested_calculation()
output = x + y; % 可以直接使用x和y
end
end
% 子函数示例(在同一个.m文件中)
function main_with_subfunctions()
% 主函数
data = [1, 2, 3, 4, 5];
processed = process_data(data);
display_results(processed);
end
function result = process_data(data)
% 子函数1
result = data .* 2 + 1;
end
function display_results(data)
% 子函数2
fprintf('处理后的数据: ');
fprintf('%d ', data);
fprintf('\n');
end
6.2.3 匿名函数和函数句柄
% 匿名函数
square_func = @(x) x.^2;
result = square_func(5); % 25
% 多参数匿名函数
add_func = @(a, b) a + b;
result = add_func(3, 4); % 7
% 复杂匿名函数
complex_func = @(x, y) sqrt(x.^2 + y.^2);
result = complex_func(3, 4); % 5
% 函数句柄
my_sin = @sin;
result = my_sin(pi/2); % 1
% 传递函数作为参数
function result = apply_function(data, func)
result = func(data);
end
data = [1, 2, 3, 4, 5];
squared = apply_function(data, @(x) x.^2);
6.2.4 递归函数
% 阶乘函数
function result = factorial_recursive(n)
if n <= 1
result = 1;
else
result = n * factorial_recursive(n - 1);
end
end
% 斐波那契数列
function result = fibonacci(n)
if n <= 1
result = n;
else
result = fibonacci(n-1) + fibonacci(n-2);
end
end
% 优化的斐波那契(使用持久变量)
function result = fibonacci_optimized(n)
persistent cache;
if isempty(cache)
cache = containers.Map('KeyType', 'int32', 'ValueType', 'double');
end
if n <= 1
result = n;
elseif isKey(cache, n)
result = cache(n);
else
result = fibonacci_optimized(n-1) + fibonacci_optimized(n-2);
cache(n) = result;
end
end
7. 数据输入输出
7.1 命令行输入输出
% 显示输出
disp('Hello, MATLAB!'); % 显示字符串
disp([1, 2, 3, 4, 5]); % 显示数组
% 格式化输出
name = 'Alice';
age = 25;
height = 1.65;
fprintf('姓名: %s, 年龄: %d, 身高: %.2f米\n', name, age, height);
% 格式化字符串
formatted_str = sprintf('圆周率: %.4f', pi);
% 用户输入
user_input = input('请输入一个数字: ');
user_string = input('请输入您的姓名: ', 's');
% 带提示的输入
choice = input('请选择 (1-是, 0-否): ');
if choice == 1
disp('您选择了是');
else
disp('您选择了否');
end
7.2 文件读写
7.2.1 文本文件操作
% 写入文本文件
filename = 'example.txt';
fileID = fopen(filename, 'w');
if fileID == -1
error('无法创建文件');
end
% 写入数据
fprintf(fileID, '这是第一行\n');
fprintf(fileID, '数字: %d, 小数: %.2f\n', 42, 3.14159);
fclose(fileID);
% 读取文本文件
fileID = fopen(filename, 'r');
if fileID == -1
error('无法打开文件');
end
% 逐行读取
line_count = 0;
while ~feof(fileID)
line = fgetl(fileID);
if ischar(line)
line_count = line_count + 1;
fprintf('第%d行: %s\n', line_count, line);
end
end
fclose(fileID);
% 一次性读取所有内容
content = fileread(filename);
disp(content);
7.2.2 CSV文件操作
% 创建示例数据
data = [1, 2, 3; 4, 5, 6; 7, 8, 9];
headers = {'A', 'B', 'C'};
% 写入CSV文件
writematrix(data, 'data.csv');
% 带标题的CSV写入
T = table(data(:,1), data(:,2), data(:,3), 'VariableNames', headers);
writetable(T, 'data_with_headers.csv');
% 读取CSV文件
loaded_data = readmatrix('data.csv');
loaded_table = readtable('data_with_headers.csv');
% 处理CSV数据
fprintf('数据维度: %dx%d\n', size(loaded_data));
fprintf('数据和: %.2f\n', sum(loaded_data, 'all'));
7.2.3 Excel文件操作
% 创建Excel文件
data = rand(10, 5);
column_names = {'列1', '列2', '列3', '列4', '列5'};
T = table(data(:,1), data(:,2), data(:,3), data(:,4), data(:,5), ...
'VariableNames', column_names);
% 写入Excel
writetable(T, 'example.xlsx', 'Sheet', 'Sheet1');
% 读取Excel
excel_data = readtable('example.xlsx');
excel_matrix = readmatrix('example.xlsx');
% 读取特定范围
range_data = readmatrix('example.xlsx', 'Range', 'A1:C5');
7.3 MAT文件操作
% 保存变量到MAT文件
a = [1, 2, 3];
b = 'Hello';
c = struct('name', 'Alice', 'age', 25);
% 保存所有变量
save('data.mat');
% 保存特定变量
save('specific_data.mat', 'a', 'b');
% 加载MAT文件
clear; % 清除当前变量
load('data.mat'); % 加载所有变量
% 加载特定变量
load('data.mat', 'a'); % 只加载变量a
% 查看MAT文件内容
file_info = whos('-file', 'data.mat');
disp(file_info);
8. 绘图与可视化
8.1 二维绘图
8.1.1 基本绘图函数
% 基本线图
x = 0:0.1:2*pi;
y = sin(x);
figure;
plot(x, y);
title('正弦函数');
xlabel('x');
ylabel('sin(x)');
grid on;
% 多条线图
x = 0:0.1:2*pi;
y1 = sin(x);
y2 = cos(x);
figure;
plot(x, y1, 'r-', x, y2, 'b--');
legend('sin(x)', 'cos(x)');
title('三角函数');
xlabel('x');
ylabel('y');
grid on;
% 散点图
x = randn(100, 1);
y = 2*x + randn(100, 1);
figure;
scatter(x, y, 50, 'filled');
title('散点图');
xlabel('x');
ylabel('y');
8.1.2 图形样式设置
% 线条样式
x = 0:0.1:2*pi;
y = sin(x);
figure;
plot(x, y, 'r-', 'LineWidth', 2, 'MarkerSize', 8);
title('自定义样式', 'FontSize', 14, 'FontWeight', 'bold');
xlabel('x', 'FontSize', 12);
ylabel('sin(x)', 'FontSize', 12);
grid on;
set(gca, 'FontSize', 10);
% 颜色映射
x = -2:0.1:2;
y = -2:0.1:2;
[X, Y] = meshgrid(x, y);
Z = X.*exp(-X.^2-Y.^2);
figure;
contourf(X, Y, Z, 20);
colorbar;
title('等高线图');
xlabel('x');
ylabel('y');
8.1.3 子图
% 创建子图
figure;
x = 0:0.1:2*pi;
% 子图1
subplot(2, 2, 1);
plot(x, sin(x));
title('sin(x)');
grid on;
% 子图2
subplot(2, 2, 2);
plot(x, cos(x));
title('cos(x)');
grid on;
% 子图3
subplot(2, 2, 3);
plot(x, tan(x));
title('tan(x)');
ylim([-5, 5]);
grid on;
% 子图4
subplot(2, 2, 4);
plot(x, exp(-x));
title('exp(-x)');
grid on;
8.2 三维绘图
% 三维线图
t = 0:0.1:3*pi;
x = cos(t);
y = sin(t);
z = t;
figure;
plot3(x, y, z);
title('三维螺旋线');
xlabel('x');
ylabel('y');
zlabel('z');
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);
title('三维曲面');
xlabel('x');
ylabel('y');
zlabel('z');
colorbar;
shading interp; % 平滑着色
% 三维散点图
x = randn(100, 1);
y = randn(100, 1);
z = randn(100, 1);
c = x + y + z; % 颜色数据
figure;
scatter3(x, y, z, 50, c, 'filled');
title('三维散点图');
xlabel('x');
ylabel('y');
zlabel('z');
colorbar;
8.3 特殊图形
% 柱状图
categories = {'A', 'B', 'C', 'D', 'E'};
values = [23, 45, 56, 78, 32];
figure;
bar(values);
set(gca, 'XTickLabel', categories);
title('柱状图');
ylabel('值');
% 饼图
labels = {'类别1', '类别2', '类别3', '类别4'};
sizes = [30, 25, 25, 20];
figure;
pie(sizes, labels);
title('饼图');
% 直方图
data = randn(1000, 1);
figure;
histogram(data, 30);
title('直方图');
xlabel('值');
ylabel('频次');
% 箱线图
groups = {'组1', '组2', '组3'};
data1 = randn(100, 1);
data2 = randn(100, 1) + 1;
data3 = randn(100, 1) + 2;
figure;
boxplot([data1; data2; data3], [ones(100,1); 2*ones(100,1); 3*ones(100,1)]);
set(gca, 'XTickLabel', groups);
title('箱线图');
ylabel('值');
9. 字符串处理
9.1 字符串基础
% 字符数组 vs 字符串数组
char_array = 'Hello World'; % 字符数组
string_array = "Hello World"; % 字符串数组
% 字符串长度
len1 = length(char_array); % 11
len2 = strlength(string_array); % 11
% 字符串连接
% 字符数组连接
combined_char = [char_array, ' MATLAB'];
combined_char2 = strcat(char_array, ' MATLAB');
% 字符串数组连接
combined_string = string_array + " MATLAB";
combined_string2 = strcat(string_array, " MATLAB");
9.2 字符串操作函数
% 字符串查找
text = "Hello World MATLAB";
pos = strfind(text, "World"); % 查找位置
contains_result = contains(text, "MATLAB"); % 是否包含
starts_result = startsWith(text, "Hello"); % 是否以...开头
ends_result = endsWith(text, "MATLAB"); % 是否以...结尾
% 字符串替换
original = "Hello World";
replaced = replace(original, "World", "MATLAB"); % "Hello MATLAB"
% 字符串分割
sentence = "apple,banana,cherry";
parts = split(sentence, ","); % ["apple"; "banana"; "cherry"]
% 字符串转换
upper_text = upper("hello world"); % "HELLO WORLD"
lower_text = lower("HELLO WORLD"); % "hello world"
title_text = title("hello world"); % "Hello World"
9.3 正则表达式
% 正则表达式匹配
text = "My phone number is 123-456-7890";
pattern = '\d{3}-\d{3}-\d{4}';
match = regexp(text, pattern, 'match'); % {'123-456-7890'}
% 提取数字
text = "Price: $25.99, Tax: $2.60";
numbers = regexp(text, '\d+\.\d+', 'match'); % {'25.99', '2.60'}
% 替换模式
email = "contact@example.com";
domain_pattern = '@\w+\.\w+';
new_email = regexprep(email, domain_pattern, '@newdomain.com');
9.4 字符串格式化
% sprintf格式化
name = "Alice";
age = 25;
formatted = sprintf("姓名: %s, 年龄: %d", name, age);
% 现代字符串格式化
formatted_modern = name + " is " + age + " years old";
% 数值格式化
pi_formatted = sprintf("π ≈ %.4f", pi);
% 日期格式化
current_date = datetime('now');
date_string = string(current_date, 'yyyy-MM-dd HH:mm:ss');
10. 结构体与元胞数组
10.1 结构体
10.1.1 结构体创建和访问
% 创建结构体
student.name = 'Alice';
student.age = 20;
student.scores = [85, 92, 78];
% 或者使用struct函数
student2 = struct('name', 'Bob', 'age', 21, 'scores', [90, 88, 95]);
% 访问结构体字段
fprintf('学生姓名: %s\n', student.name);
fprintf('平均分: %.2f\n', mean(student.scores));
10.1.2 结构体数组
% 创建结构体数组
students(1) = struct('name', 'Alice', 'age', 20, 'scores', [85, 92, 78]);
students(2) = struct('name', 'Bob', 'age', 21, 'scores', [90, 88, 95]);
students(3) = struct('name', 'Charlie', 'age', 19, 'scores', [88, 90, 92]);
% 访问结构体数组
for i = 1:length(students)
fprintf('学生%d: %s, 年龄: %d, 平均分: %.2f\n', ...
i, students(i).name, students(i).age, mean(students(i).scores));
end
% 提取特定字段
names = {students.name}; % 所有姓名
ages = [students.age]; % 所有年龄
10.1.3 嵌套结构体
% 嵌套结构体
company.name = 'Tech Corp';
company.employees(1).name = 'Alice';
company.employees(1).position = 'Engineer';
company.employees(1).salary = 75000;
company.employees(2).name = 'Bob';
company.employees(2).position = 'Manager';
company.employees(2).salary = 85000;
% 访问嵌套结构体
fprintf('公司: %s\n', company.name);
for i = 1:length(company.employees)
emp = company.employees(i);
fprintf('员工%d: %s, 职位: %s, 薪资: $%d\n', ...
i, emp.name, emp.position, emp.salary);
end
10.2 元胞数组
10.2.1 元胞数组创建
% 创建元胞数组
cell_array = {'Hello', 42, [1, 2, 3], true};
% 预分配元胞数组
large_cell = cell(3, 3);
large_cell{1, 1} = 'Text';
large_cell{1, 2} = 123;
large_cell{2, 1} = [1, 2, 3; 4, 5, 6];
% 混合数据类型
mixed_data = {
'Name', 'Alice';
'Age', 25;
'Scores', [85, 92, 78];
'Graduate', true
};
10.2.2 元胞数组操作
% 访问元胞数组
first_element = cell_array{1}; % 'Hello'
second_element = cell_array{2}; % 42
% 修改元胞数组
cell_array{1} = 'Modified';
% 元胞数组大小
[rows, cols] = size(mixed_data);
total_elements = numel(cell_array);
% 元胞数组转换
if all(cellfun(@isnumeric, cell_array(2:3)))
numeric_part = cell2mat(cell_array(2:3));
end
10.2.3 元胞数组的高级操作
% 使用cellfun处理元胞数组
numbers_cell = {[1, 2, 3], [4, 5], [6, 7, 8, 9]};
lengths = cellfun(@length, numbers_cell); % [3, 2, 4]
means = cellfun(@mean, numbers_cell); % [2, 4.5, 6.5]
% 字符串元胞数组操作
names = {'Alice', 'Bob', 'Charlie'};
name_lengths = cellfun(@length, names);
upper_names = cellfun(@upper, names, 'UniformOutput', false);
% 元胞数组排序
[sorted_names, indices] = sort(names);
11. 文件操作
11.1 文件系统操作
% 当前目录操作
current_dir = pwd; % 获取当前目录
cd('/path/to/directory'); % 改变目录
cd(current_dir); % 返回原目录
% 文件和目录信息
file_info = dir('*.m'); % 列出所有.m文件
folder_info = dir(); % 列出当前目录所有内容
% 检查文件/目录存在性
if exist('data.mat', 'file')
disp('文件存在');
end
if exist('my_folder', 'dir')
disp('目录存在');
end
% 创建和删除目录
if ~exist('temp_folder', 'dir')
mkdir('temp_folder');
end
rmdir('temp_folder'); % 删除空目录
11.2 文件路径操作
% 路径构建
full_path = fullfile('data', 'results', 'output.txt');
% 路径分析
[path, name, ext] = fileparts(full_path);
fprintf('路径: %s\n', path);
fprintf('文件名: %s\n', name);
fprintf('扩展名: %s\n', ext);
% 相对路径和绝对路径
relative_path = 'data/file.txt';
absolute_path = fullfile(pwd, relative_path);
11.3 批量文件处理
% 批量处理文件
file_list = dir('*.txt');
for i = 1:length(file_list)
filename = file_list(i).name;
fprintf('处理文件: %s\n', filename);
% 读取文件
content = fileread(filename);
% 处理内容(示例:转换为大写)
processed_content = upper(content);
% 保存处理后的文件
new_filename = ['processed_', filename];
fid = fopen(new_filename, 'w');
fprintf(fid, '%s', processed_content);
fclose(fid);
end
12. 调试与错误处理
12.1 调试技巧
% 断点调试
function debug_example()
x = 1:10;
y = x.^2;
% 在此处设置断点
keyboard; % 手动断点
z = y + x;
result = sum(z);
fprintf('结果: %d\n', result);
end
% 条件断点
function conditional_debug()
for i = 1:100
value = rand();
if value > 0.95
keyboard; % 当条件满足时暂停
end
end
end
12.2 错误处理策略
% 完整的错误处理示例
function safe_divide(a, b)
try
% 参数验证
if nargin < 2
error('需要两个输入参数');
end
if ~isnumeric(a) || ~isnumeric(b)
error('输入必须是数值');
end
if b == 0
warning('除数为零,返回Inf');
result = Inf;
else
result = a / b;
end
fprintf('结果: %.4f\n', result);
catch ME
% 错误处理
fprintf('错误类型: %s\n', ME.identifier);
fprintf('错误信息: %s\n', ME.message);
% 记录错误
log_error(ME);
% 重新抛出特定错误
if strcmp(ME.identifier, 'MATLAB:narginchk:notEnoughInputs')
rethrow(ME);
end
end
end
function log_error(error_info)
% 错误日志记录
log_file = 'error_log.txt';
fid = fopen(log_file, 'a');
fprintf(fid, '[%s] %s: %s\n', datestr(now), error_info.identifier, error_info.message);
fclose(fid);
end
13. 性能优化
13.1 向量化操作
% 避免循环,使用向量化
% 低效的循环方式
tic;
n = 1000000;
result_loop = zeros(n, 1);
for i = 1:n
result_loop(i) = sin(i) + cos(i);
end
time_loop = toc;
% 高效的向量化方式
tic;
x = 1:n;
result_vectorized = sin(x) + cos(x);
time_vectorized = toc;
fprintf('循环时间: %.4f秒\n', time_loop);
fprintf('向量化时间: %.4f秒\n', time_vectorized);
fprintf('速度提升: %.2f倍\n', time_loop / time_vectorized);
13.2 内存管理
% 预分配数组
% 低效方式
tic;
slow_array = [];
for i = 1:10000
slow_array(end+1) = i^2;
end
time_slow = toc;
% 高效方式
tic;
fast_array = zeros(10000, 1);
for i = 1:10000
fast_array(i) = i^2;
end
time_fast = toc;
fprintf('动态分配时间: %.4f秒\n', time_slow);
fprintf('预分配时间: %.4f秒\n', time_fast);
13.3 性能分析
% 使用profile进行性能分析
profile on;
complex_calculation();
profile off;
profile viewer; % 查看性能报告
function complex_calculation()
% 复杂计算示例
data = randn(1000, 1000);
% 矩阵运算
result1 = data * data';
% 统计计算
result2 = mean(data, 2);
% 排序
result3 = sort(data, 2);
end
14. 工具箱简介
14.1 常用工具箱
14.1.1 Signal Processing Toolbox(信号处理工具箱)
% 信号处理示例
fs = 1000; % 采样频率
t = 0:1/fs:1-1/fs; % 时间向量
f1 = 50; f2 = 120; % 频率
signal = sin(2*pi*f1*t) + 0.5*sin(2*pi*f2*t);
% 添加噪声
noisy_signal = signal + 0.2*randn(size(t));
% 设计滤波器
[b, a] = butter(4, 100/(fs/2)); % 4阶低通滤波器
filtered_signal = filter(b, a, noisy_signal);
% 绘图
figure;
subplot(3,1,1);
plot(t, signal);
title('原始信号');
subplot(3,1,2);
plot(t, noisy_signal);
title('带噪声信号');
subplot(3,1,3);
plot(t, filtered_signal);
title('滤波后信号');
% 频谱分析
figure;
Y = fft(noisy_signal);
f = (0:length(Y)-1)*fs/length(Y);
plot(f, abs(Y));
title('频谱分析');
xlabel('频率 (Hz)');
ylabel('幅度');
14.1.2 Image Processing Toolbox(图像处理工具箱)
% 图像处理示例
% 读取图像
img = imread('cameraman.tif'); % MATLAB自带图像
figure;
subplot(2,3,1);
imshow(img);
title('原图');
% 直方图均衡化
img_eq = histeq(img);
subplot(2,3,2);
imshow(img_eq);
title('直方图均衡化');
% 边缘检测
edges = edge(img, 'canny');
subplot(2,3,3);
imshow(edges);
title('边缘检测');
% 高斯滤波
img_filtered = imgaussfilt(img, 2);
subplot(2,3,4);
imshow(img_filtered);
title('高斯滤波');
% 形态学操作
se = strel('disk', 3);
img_morph = imopen(img, se);
subplot(2,3,5);
imshow(img_morph);
title('形态学开运算');
% 图像分割
level = graythresh(img);
img_bw = imbinarize(img, level);
subplot(2,3,6);
imshow(img_bw);
title('二值化');
14.1.3 Statistics and Machine Learning Toolbox(统计和机器学习工具箱)
% 统计分析示例
rng(42); % 设置随机种子
data = randn(1000, 2);
data(:,2) = data(:,2) + 0.5*data(:,1); % 添加相关性
% 描述性统计
mean_vals = mean(data);
std_vals = std(data);
corr_matrix = corrcoef(data);
fprintf('均值: [%.2f, %.2f]\n', mean_vals(1), mean_vals(2));
fprintf('标准差: [%.2f, %.2f]\n', std_vals(1), std_vals(2));
fprintf('相关系数: %.2f\n', corr_matrix(1,2));
% 机器学习示例 - 聚类
% 生成聚类数据
cluster1 = mvnrnd([2, 2], [1, 0.5; 0.5, 1], 100);
cluster2 = mvnrnd([-2, -2], [1, -0.5; -0.5, 1], 100);
cluster3 = mvnrnd([2, -2], [1, 0; 0, 1], 100);
ml_data = [cluster1; cluster2; cluster3];
% K-means聚类
[idx, centers] = kmeans(ml_data, 3);
% 可视化聚类结果
figure;
colors = ['r', 'g', 'b'];
for i = 1:3
scatter(ml_data(idx==i, 1), ml_data(idx==i, 2), colors(i), 'filled');
hold on;
end
scatter(centers(:,1), centers(:,2), 100, 'k', 'x', 'LineWidth', 2);
title('K-means聚类结果');
legend('聚类1', '聚类2', '聚类3', '聚类中心');
14.1.4 Optimization Toolbox(优化工具箱)
% 优化问题示例
% 目标函数:最小化 f(x) = x1^2 + x2^2 + x1*x2
objective = @(x) x(1)^2 + x(2)^2 + x(1)*x(2);
% 初始点
x0 = [1, 1];
% 约束条件
% 不等式约束: x1 + x2 <= 2
A = [1, 1];
b = 2;
% 等式约束: x1 - x2 = 0
Aeq = [1, -1];
beq = 0;
% 求解
options = optimoptions('fmincon', 'Display', 'iter');
[x_optimal, fval] = fmincon(objective, x0, A, b, Aeq, beq, [], [], [], options);
fprintf('最优解: x = [%.4f, %.4f]\n', x_optimal(1), x_optimal(2));
fprintf('最优值: f = %.4f\n', fval);
14.1.5 Control System Toolbox(控制系统工具箱)
% 控制系统示例
% 传递函数
num = [1, 2];
den = [1, 3, 2];
sys = tf(num, den);
% 系统分析
figure;
subplot(2,2,1);
step(sys);
title('阶跃响应');
subplot(2,2,2);
impulse(sys);
title('脉冲响应');
subplot(2,2,3);
bode(sys);
title('波德图');
subplot(2,2,4);
nyquist(sys);
title('奈奎斯特图');
% 极点和零点
poles = pole(sys);
zeros = zero(sys);
fprintf('极点: ');
disp(poles');
fprintf('零点: ');
disp(zeros');
14.2 工具箱函数查找
% 查看已安装的工具箱
ver
% 查看特定工具箱的函数
help signal % 信号处理工具箱
help images % 图像处理工具箱
help stats % 统计工具箱
% 搜索特定功能
lookfor filter % 搜索包含"filter"的函数
15. 实战项目
15.1 项目1:数据分析与可视化
% 项目:分析股票数据
% 生成模拟股票数据
days = 1:252; % 一年的交易日
initial_price = 100;
returns = 0.001 + 0.02*randn(1, 252); % 日收益率
prices = initial_price * cumprod(1 + returns);
% 计算技术指标
function sma = simple_moving_average(data, window)
sma = zeros(size(data));
for i = window:length(data)
sma(i) = mean(data(i-window+1:i));
end
end
sma_20 = simple_moving_average(prices, 20);
sma_50 = simple_moving_average(prices, 50);
% 计算波动率
volatility = movstd(returns, 20) * sqrt(252);
% 绘制分析图表
figure('Position', [100, 100, 1200, 800]);
% 价格和移动平均线
subplot(3,1,1);
plot(days, prices, 'b-', 'LineWidth', 1.5);
hold on;
plot(days, sma_20, 'r--', 'LineWidth', 1);
plot(days, sma_50, 'g--', 'LineWidth', 1);
title('股票价格和移动平均线');
legend('价格', '20日均线', '50日均线');
ylabel('价格');
grid on;
% 日收益率
subplot(3,1,2);
plot(days, returns*100, 'k-');
title('日收益率');
ylabel('收益率 (%)');
grid on;
% 波动率
subplot(3,1,3);
plot(days, volatility*100, 'm-', 'LineWidth', 1.5);
title('20日滚动波动率');
ylabel('波动率 (%)');
xlabel('交易日');
grid on;
% 统计摘要
fprintf('=== 股票分析报告 ===\n');
fprintf('期初价格: $%.2f\n', prices(1));
fprintf('期末价格: $%.2f\n', prices(end));
fprintf('总收益率: %.2f%%\n', (prices(end)/prices(1) - 1)*100);
fprintf('平均日收益率: %.4f%%\n', mean(returns)*100);
fprintf('波动率: %.2f%%\n', std(returns)*sqrt(252)*100);
fprintf('最大回撤: %.2f%%\n', max(cummax(prices) - prices)./cummax(prices)*100);
15.2 项目2:信号处理应用
% 项目:音频信号处理
% 生成复合音频信号
fs = 44100; % 采样率
duration = 3; % 持续时间
t = 0:1/fs:duration-1/fs;
% 创建复合信号
freq1 = 440; % A4音符
freq2 = 880; % A5音符
freq3 = 1320; % E6音符
signal = sin(2*pi*freq1*t) + 0.5*sin(2*pi*freq2*t) + 0.3*sin(2*pi*freq3*t);
% 添加噪声
noisy_signal = signal + 0.1*randn(size(t));
% 设计滤波器组
% 低通滤波器 (< 600 Hz)
[b_low, a_low] = butter(6, 600/(fs/2), 'low');
low_freq = filter(b_low, a_low, noisy_signal);
% 带通滤波器 (600-1000 Hz)
[b_band, a_band] = butter(6, [600, 1000]/(fs/2), 'bandpass');
mid_freq = filter(b_band, a_band, noisy_signal);
% 高通滤波器 (> 1000 Hz)
[b_high, a_high] = butter(6, 1000/(fs/2), 'high');
high_freq = filter(b_high, a_high, noisy_signal);
% 频谱分析
N = length(noisy_signal);
f = (0:N-1)*(fs/N);
Y_original = fft(signal);
Y_noisy = fft(noisy_signal);
Y_filtered = fft(low_freq + mid_freq + high_freq);
% 绘制结果
figure('Position', [100, 100, 1200, 900]);
% 时域信号
subplot(3,2,1);
plot(t(1:fs/10), signal(1:fs/10));
title('原始信号(前0.1秒)');
xlabel('时间 (s)');
ylabel('幅度');
subplot(3,2,2);
plot(t(1:fs/10), noisy_signal(1:fs/10));
title('含噪声信号(前0.1秒)');
xlabel('时间 (s)');
ylabel('幅度');
% 频谱
subplot(3,2,3);
plot(f(1:N/2), abs(Y_original(1:N/2)));
title('原始信号频谱');
xlabel('频率 (Hz)');
ylabel('幅度');
subplot(3,2,4);
plot(f(1:N/2), abs(Y_noisy(1:N/2)));
title('含噪声信号频谱');
xlabel('频率 (Hz)');
ylabel('幅度');
% 滤波后的信号
subplot(3,2,5);
plot(t(1:fs/10), (low_freq + mid_freq + high_freq)(1:fs/10));
title('滤波后信号(前0.1秒)');
xlabel('时间 (s)');
ylabel('幅度');
subplot(3,2,6);
plot(f(1:N/2), abs(Y_filtered(1:N/2)));
title('滤波后信号频谱');
xlabel('频率 (Hz)');
ylabel('幅度');
% 保存音频文件(如果需要)
% audiowrite('original_signal.wav', signal, fs);
% audiowrite('noisy_signal.wav', noisy_signal, fs);
% audiowrite('filtered_signal.wav', low_freq + mid_freq + high_freq, fs);
15.3 项目3:图像处理应用
% 项目:图像增强和特征提取
% 读取图像(使用MATLAB自带的图像)
img = imread('coins.png');
if size(img, 3) == 3
img_gray = rgb2gray(img);
else
img_gray = img;
end
% 图像预处理
img_enhanced = imadjust(img_gray); % 对比度增强
img_filtered = imgaussfilt(img_enhanced, 1); % 高斯滤波
% 边缘检测
edges = edge(img_filtered, 'canny');
% 形态学处理
se = strel('disk', 3);
img_closed = imclose(edges, se);
img_filled = imfill(img_closed, 'holes');
% 连通组件分析
[labeled, num_objects] = bwlabel(img_filled);
stats = regionprops(labeled, 'Area', 'Centroid', 'BoundingBox', 'Eccentricity');
% 过滤小对象
min_area = 500;
large_objects = [stats.Area] > min_area;
stats_filtered = stats(large_objects);
% 创建结果图像
result_img = img_gray;
figure('Position', [100, 100, 1200, 800]);
% 显示处理过程
subplot(2,3,1);
imshow(img_gray);
title('原图');
subplot(2,3,2);
imshow(img_enhanced);
title('对比度增强');
subplot(2,3,3);
imshow(edges);
title('边缘检测');
subplot(2,3,4);
imshow(img_filled);
title('形态学处理');
subplot(2,3,5);
imshow(img_gray);
hold on;
for i = 1:length(stats_filtered)
centroid = stats_filtered(i).Centroid;
plot(centroid(1), centroid(2), 'r+', 'MarkerSize', 10, 'LineWidth', 2);
% 绘制边界框
bbox = stats_filtered(i).BoundingBox;
rectangle('Position', bbox, 'EdgeColor', 'g', 'LineWidth', 2);
end
title(sprintf('检测到的对象 (共%d个)', length(stats_filtered)));
subplot(2,3,6);
areas = [stats_filtered.Area];
histogram(areas, 10);
title('对象面积分布');
xlabel('面积 (像素)');
ylabel('数量');
% 输出统计信息
fprintf('=== 图像分析报告 ===\n');
fprintf('图像尺寸: %d × %d\n', size(img_gray, 1), size(img_gray, 2));
fprintf('检测到的对象数量: %d\n', length(stats_filtered));
fprintf('平均对象面积: %.2f 像素\n', mean(areas));
fprintf('最大对象面积: %.2f 像素\n', max(areas));
fprintf('最小对象面积: %.2f 像素\n', min(areas));
15.4 项目4:数值计算应用
% 项目:求解偏微分方程(热传导方程)
% 参数设置
L = 1; % 长度
T = 0.1; % 时间
alpha = 0.01; % 热扩散系数
nx = 50; % 空间网格数
nt = 1000; % 时间步数
% 网格
dx = L / (nx - 1);
dt = T / nt;
x = 0:dx:L;
t = 0:dt:T;
% 稳定性检查
r = alpha * dt / dx^2;
if r > 0.5
warning('数值不稳定,r = %.3f > 0.5', r);
end
% 初始条件
u = zeros(nx, nt+1);
u(:, 1) = sin(pi * x); % 初始温度分布
% 边界条件(两端为0)
u(1, :) = 0;
u(end, :) = 0;
% 有限差分求解
for n = 1:nt
for i = 2:nx-1
u(i, n+1) = u(i, n) + r * (u(i+1, n) - 2*u(i, n) + u(i-1, n));
end
end
% 解析解(用于验证)
u_analytical = zeros(nx, length(t));
for i = 1:length(t)
u_analytical(:, i) = exp(-pi^2 * alpha * t(i)) * sin(pi * x);
end
% 绘制结果
figure('Position', [100, 100, 1200, 800]);
% 3D图
subplot(2,2,1);
[T_mesh, X_mesh] = meshgrid(t, x);
surf(T_mesh, X_mesh, u);
title('热传导方程数值解');
xlabel('时间');
ylabel('位置');
zlabel('温度');
% 不同时间点的温度分布
subplot(2,2,2);
time_points = [1, 101, 301, 501, 1001];
colors = ['b', 'r', 'g', 'm', 'k'];
for i = 1:length(time_points)
plot(x, u(:, time_points(i)), colors(i), 'LineWidth', 2);
hold on;
end
title('不同时间点的温度分布');
xlabel('位置');
ylabel('温度');
legend('t=0', 't=0.01', 't=0.03', 't=0.05', 't=0.1');
% 数值解vs解析解
subplot(2,2,3);
final_time_idx = length(t);
plot(x, u(:, final_time_idx), 'b-', 'LineWidth', 2);
hold on;
plot(x, u_analytical(:, final_time_idx), 'r--', 'LineWidth', 2);
title('t=0.1时的数值解与解析解比较');
xlabel('位置');
ylabel('温度');
legend('数值解', '解析解');
% 误差分析
subplot(2,2,4);
error = abs(u(:, final_time_idx) - u_analytical(:, final_time_idx));
plot(x, error, 'r-', 'LineWidth', 2);
title('数值解误差');
xlabel('位置');
ylabel('绝对误差');
fprintf('=== 数值计算报告 ===\n');
fprintf('网格数: %d\n', nx);
fprintf('时间步数: %d\n', nt);
fprintf('稳定性参数 r: %.3f\n', r);
fprintf('最大误差: %.6f\n', max(error));
fprintf('平均误差: %.6f\n', mean(error));
16. 常见问题与解决方案
16.1 常见错误及解决方法
16.1.1 索引错误
% 错误示例
A = [1, 2, 3];
try
value = A(0); % MATLAB索引从1开始,不是0
catch ME
fprintf('错误: %s\n', ME.message);
end
% 正确方法
value = A(1); % 获取第一个元素
% 动态索引检查
function safe_index = get_safe_index(array, index)
if index < 1 || index > length(array)
error('索引超出范围');
end
safe_index = array(index);
end
16.1.2 维度不匹配
% 错误示例
A = [1, 2, 3]; % 1×3
B = [4; 5; 6]; % 3×1
try
C = A + B;
catch ME
fprintf('错误: %s\n', ME.message);
end
% 解决方法1:转置
C1 = A + B'; % 1×3 + 1×3
% 解决方法2:使用广播
C2 = A + B'; % 自动广播
% 解决方法3:显式重塑
C3 = A + reshape(B, 1, 3);
16.1.3 数据类型问题
% 整数溢出
a = uint8(255);
b = uint8(10);
c = a + b; % 溢出,结果为255而不是265
fprintf('uint8溢出: %d + %d = %d\n', a, b, c);
% 解决方法:使用更大的数据类型
a_double = double(a);
b_double = double(b);
c_correct = a_double + b_double;
fprintf('正确结果: %.0f + %.0f = %.0f\n', a_double, b_double, c_correct);
16.2 性能问题诊断
16.2.1 内存使用监控
% 监控内存使用
function memory_demo()
% 获取当前内存使用
memory_info = memory;
fprintf('可用内存: %.2f GB\n', memory_info.MemAvailableAllArrays / 1e9);
% 创建大数组
fprintf('创建大数组...\n');
big_array = randn(10000, 10000);
% 检查内存使用
memory_info = memory;
fprintf('使用后可用内存: %.2f GB\n', memory_info.MemAvailableAllArrays / 1e9);
% 清理内存
clear big_array;
fprintf('清理后可用内存: %.2f GB\n', memory.MemAvailableAllArrays / 1e9);
end
memory_demo();
16.2.2 代码剖析
% 性能测试函数
function performance_comparison()
n = 1000;
% 方法1:循环
tic;
result1 = zeros(n, 1);
for i = 1:n
result1(i) = sin(i) * cos(i);
end
time1 = toc;
% 方法2:向量化
tic;
x = (1:n)';
result2 = sin(x) .* cos(x);
time2 = toc;
% 方法3:内置函数
tic;
x = (1:n)';
result3 = 0.5 * sin(2*x); % 使用三角恒等式
time3 = toc;
fprintf('循环方法: %.6f 秒\n', time1);
fprintf('向量化方法: %.6f 秒\n', time2);
fprintf('优化方法: %.6f 秒\n', time3);
% 验证结果一致性
fprintf('结果一致性: %s\n', ...
isequal(round(result1, 10), round(result2, 10), round(result3, 10)));
end
performance_comparison();
16.3 调试技巧
16.3.1 断点和单步执行
% 调试示例函数
function result = debug_example(x)
% 设置断点:在此行左边点击
y = x.^2;
% 条件断点
if any(y > 100)
disp('发现大值'); % 在此设置断点
end
% 变量检查
z = sin(y);
result = sum(z);
end
% 调试命令
% dbstop in debug_example at 3 % 在第3行设置断点
% dbclear all % 清除所有断点
% dbstack % 显示调用栈
16.3.2 异常处理
% 健壮的异常处理
function robust_calculation(data)
try
% 输入验证
if ~isnumeric(data)
error('输入必须是数值');
end
if any(isnan(data))
warning('数据包含NaN值,将被忽略');
data = data(~isnan(data));
end
% 主要计算
result = sqrt(mean(data.^2));
fprintf('RMS值: %.4f\n', result);
catch ME
fprintf('错误发生在: %s\n', ME.stack(1).name);
fprintf('错误行号: %d\n', ME.stack(1).line);
fprintf('错误信息: %s\n', ME.message);
% 记录错误
error_log = struct('time', datetime, 'error', ME.message, 'data_size', size(data));
save('error_log.mat', 'error_log', '-append');
end
end
% 测试异常处理
robust_calculation([1, 2, 3, NaN, 5]);
robust_calculation('invalid');
16.4 最佳实践总结
16.4.1 编程风格
% 好的编程风格示例
function [mean_val, std_val, processed_data] = process_data(input_data, options)
% PROCESS_DATA 处理输入数据并返回统计信息
%
% 输入:
% input_data - 数值数组
% options - 处理选项结构体
%
% 输出:
% mean_val - 平均值
% std_val - 标准差
% processed_data - 处理后的数据
% 输入验证
arguments
input_data (:,:) double
options.remove_outliers (1,1) logical = false
options.normalize (1,1) logical = false
end
% 初始化
processed_data = input_data;
% 移除异常值
if options.remove_outliers
q1 = quantile(processed_data, 0.25);
q3 = quantile(processed_data, 0.75);
iqr = q3 - q1;
outliers = processed_data < (q1 - 1.5*iqr) | processed_data > (q3 + 1.5*iqr);
processed_data(outliers) = NaN;
end
% 标准化
if options.normalize
processed_data = (processed_data - mean(processed_data, 'omitnan')) / ...
std(processed_data, 'omitnan');
end
% 计算统计量
mean_val = mean(processed_data, 'omitnan');
std_val = std(processed_data, 'omitnan');
% 记录处理信息
fprintf('处理完成: 均值=%.4f, 标准差=%.4f\n', mean_val, std_val);
end
% 使用示例
data = randn(1000, 1) + [zeros(950, 1); 10*ones(50, 1)]; % 包含异常值
[m, s, clean_data] = process_data(data, 'remove_outliers', true, 'normalize', true);
16.4.2 代码组织
% 主函数
function main()
% 设置参数
config = load_config();
% 加载数据
data = load_data(config.data_file);
% 处理数据
results = process_all_data(data, config);
% 保存结果
save_results(results, config.output_file);
% 生成报告
generate_report(results);
end
% 配置加载函数
function config = load_config()
config.data_file = 'input_data.mat';
config.output_file = 'results.mat';
config.processing_options.filter_type = 'gaussian';
config.processing_options.window_size = 10;
config.visualization.create_plots = true;
config.visualization.save_figures = true;
end
% 数据加载函数
function data = load_data(filename)
if exist(filename, 'file')
load(filename, 'data');
else
warning('数据文件不存在,使用模拟数据');
data = generate_sample_data();
end
end
% 数据处理函数
function results = process_all_data(data, config)
results = struct();
results.raw_statistics = calculate_statistics(data);
results.filtered_data = apply_filter(data, config.processing_options);
results.processed_statistics = calculate_statistics(results.filtered_data);
if config.visualization.create_plots
results.figures = create_visualizations(data, results.filtered_data);
end
end
16.5 高级技巧和技术
16.5.1 面向对象编程
% 定义一个数据分析类
classdef DataAnalyzer < handle
% DATAANALYZER 数据分析器类
properties (Access = public)
data % 原始数据
processed_data % 处理后的数据
statistics % 统计信息
options % 处理选项
end
properties (Access = private)
is_processed = false % 是否已处理
end
methods
function obj = DataAnalyzer(input_data, varargin)
% 构造函数
obj.data = input_data;
obj.options = obj.parse_options(varargin{:});
obj.statistics = struct();
end
function process(obj)
% 处理数据
obj.processed_data = obj.data;
% 移除异常值
if obj.options.remove_outliers
obj.processed_data = obj.remove_outliers(obj.processed_data);
end
% 应用滤波
if ~isempty(obj.options.filter_type)
obj.processed_data = obj.apply_filter(obj.processed_data);
end
% 计算统计量
obj.calculate_statistics();
obj.is_processed = true;
end
function visualize(obj)
% 可视化结果
if ~obj.is_processed
error('请先调用process()方法');
end
figure('Position', [100, 100, 1200, 600]);
subplot(2,2,1);
plot(obj.data);
title('原始数据');
ylabel('值');
subplot(2,2,2);
plot(obj.processed_data);
title('处理后数据');
ylabel('值');
subplot(2,2,3);
histogram(obj.data, 30);
title('原始数据直方图');
xlabel('值');
ylabel('频数');
subplot(2,2,4);
histogram(obj.processed_data, 30);
title('处理后数据直方图');
xlabel('值');
ylabel('频数');
end
function report = generate_report(obj)
% 生成报告
if ~obj.is_processed
error('请先调用process()方法');
end
report = struct();
report.original_stats = obj.statistics.original;
report.processed_stats = obj.statistics.processed;
report.improvement = obj.calculate_improvement();
% 打印报告
fprintf('\n=== 数据分析报告 ===\n');
fprintf('原始数据统计:\n');
fprintf(' 均值: %.4f\n', report.original_stats.mean);
fprintf(' 标准差: %.4f\n', report.original_stats.std);
fprintf(' 范围: [%.4f, %.4f]\n', report.original_stats.min, report.original_stats.max);
fprintf('\n处理后数据统计:\n');
fprintf(' 均值: %.4f\n', report.processed_stats.mean);
fprintf(' 标准差: %.4f\n', report.processed_stats.std);
fprintf(' 范围: [%.4f, %.4f]\n', report.processed_stats.min, report.processed_stats.max);
fprintf('\n改善情况:\n');
fprintf(' 标准差减少: %.2f%%\n', report.improvement.std_reduction * 100);
fprintf(' 信噪比提升: %.2f dB\n', report.improvement.snr_improvement);
end
end
methods (Access = private)
function options = parse_options(obj, varargin)
% 解析输入选项
p = inputParser;
addParameter(p, 'remove_outliers', false, @islogical);
addParameter(p, 'filter_type', 'none', @ischar);
addParameter(p, 'filter_window', 5, @isnumeric);
parse(p, varargin{:});
options = p.Results;
end
function data = remove_outliers(obj, data)
% 移除异常值
q1 = quantile(data, 0.25);
q3 = quantile(data, 0.75);
iqr = q3 - q1;
outliers = data < (q1 - 1.5*iqr) | data > (q3 + 1.5*iqr);
data(outliers) = NaN;
end
function data = apply_filter(obj, data)
% 应用滤波器
switch obj.options.filter_type
case 'moving_average'
data = movmean(data, obj.options.filter_window, 'omitnan');
case 'gaussian'
data = smoothdata(data, 'gaussian', obj.options.filter_window);
case 'median'
data = movmedian(data, obj.options.filter_window, 'omitnan');
end
end
function calculate_statistics(obj)
% 计算统计量
obj.statistics.original = obj.compute_stats(obj.data);
obj.statistics.processed = obj.compute_stats(obj.processed_data);
end
function stats = compute_stats(obj, data)
% 计算基本统计量
stats.mean = mean(data, 'omitnan');
stats.std = std(data, 'omitnan');
stats.min = min(data, [], 'omitnan');
stats.max = max(data, [], 'omitnan');
stats.median = median(data, 'omitnan');
stats.count = sum(~isnan(data));
end
function improvement = calculate_improvement(obj)
% 计算改善指标
original_std = obj.statistics.original.std;
processed_std = obj.statistics.processed.std;
improvement.std_reduction = (original_std - processed_std) / original_std;
improvement.snr_improvement = 20 * log10(original_std / processed_std);
end
end
end
% 使用示例
data = randn(1000, 1) + 0.5*sin(0.1*(1:1000)') + [zeros(950, 1); 5*randn(50, 1)];
analyzer = DataAnalyzer(data, 'remove_outliers', true, 'filter_type', 'gaussian', 'filter_window', 10);
analyzer.process();
analyzer.visualize();
report = analyzer.generate_report();
16.5.2 并行计算
% 并行计算示例
function parallel_computing_demo()
% 检查并行计算工具箱
if ~license('test', 'Distrib_Computing_Toolbox')
warning('未安装并行计算工具箱');
return;
end
% 启动并行池
if isempty(gcp('nocreate'))
parpool('local', 4); % 启动4个工作进程
end
% 数据准备
n = 1000;
matrices = cell(n, 1);
for i = 1:n
matrices{i} = randn(100, 100);
end
% 串行计算
tic;
serial_results = zeros(n, 1);
for i = 1:n
serial_results(i) = det(matrices{i});
end
serial_time = toc;
% 并行计算
tic;
parallel_results = zeros(n, 1);
parfor i = 1:n
parallel_results(i) = det(matrices{i});
end
parallel_time = toc;
% 比较结果
fprintf('串行计算时间: %.4f 秒\n', serial_time);
fprintf('并行计算时间: %.4f 秒\n', parallel_time);
fprintf('加速比: %.2f\n', serial_time / parallel_time);
fprintf('结果一致性: %s\n', mat2str(norm(serial_results - parallel_results) < 1e-10));
end
% 并行数据处理示例
function parallel_data_processing()
% 生成大量数据集
num_datasets = 20;
datasets = cell(num_datasets, 1);
for i = 1:num_datasets
datasets{i} = randn(10000, 1) + sin(0.01*(1:10000)');
end
% 并行处理函数
function result = process_dataset(data)
% 复杂的数据处理
filtered = smoothdata(data, 'gaussian', 50);
fft_result = fft(filtered);
power_spectrum = abs(fft_result).^2;
result = struct('mean', mean(data), 'std', std(data), ...
'max_freq', max(power_spectrum), 'energy', sum(power_spectrum));
end
% 并行处理
tic;
results = cell(num_datasets, 1);
parfor i = 1:num_datasets
results{i} = process_dataset(datasets{i});
end
parallel_time = toc;
fprintf('并行处理%d个数据集用时: %.4f 秒\n', num_datasets, parallel_time);
% 汇总结果
means = cellfun(@(x) x.mean, results);
stds = cellfun(@(x) x.std, results);
fprintf('平均值范围: [%.4f, %.4f]\n', min(means), max(means));
fprintf('标准差范围: [%.4f, %.4f]\n', min(stds), max(stds));
end
% 运行并行计算示例
parallel_computing_demo();
parallel_data_processing();
16.5.3 GPU计算
% GPU计算示例
function gpu_computing_demo()
% 检查GPU支持
if ~canUseGPU()
warning('GPU不可用或未安装Parallel Computing Toolbox');
return;
end
% 显示GPU信息
gpu_info = gpuDevice();
fprintf('GPU: %s\n', gpu_info.Name);
fprintf('GPU内存: %.2f GB\n', gpu_info.TotalMemory / 1e9);
% 创建大矩阵
n = 5000;
A_cpu = randn(n, n);
B_cpu = randn(n, n);
% CPU计算
tic;
C_cpu = A_cpu * B_cpu;
cpu_time = toc;
% GPU计算
A_gpu = gpuArray(A_cpu);
B_gpu = gpuArray(B_cpu);
tic;
C_gpu = A_gpu * B_gpu;
wait(gpu_info); % 等待GPU计算完成
gpu_time = toc;
% 将结果传回CPU
C_gpu_result = gather(C_gpu);
% 比较结果
fprintf('CPU计算时间: %.4f 秒\n', cpu_time);
fprintf('GPU计算时间: %.4f 秒\n', gpu_time);
fprintf('加速比: %.2f\n', cpu_time / gpu_time);
fprintf('结果误差: %.2e\n', norm(C_cpu - C_gpu_result, 'fro') / norm(C_cpu, 'fro'));
% 清理GPU内存
clear A_gpu B_gpu C_gpu;
end
% GPU信号处理示例
function gpu_signal_processing()
if ~canUseGPU()
return;
end
% 生成信号
fs = 1000;
t = 0:1/fs:10-1/fs;
signal_cpu = sin(2*pi*50*t) + 0.5*sin(2*pi*120*t) + 0.2*randn(size(t));
% 传输到GPU
signal_gpu = gpuArray(signal_cpu);
% GPU上的FFT
tic;
fft_gpu = fft(signal_gpu);
power_spectrum_gpu = abs(fft_gpu).^2;
gpu_fft_time = toc;
% CPU上的FFT
tic;
fft_cpu = fft(signal_cpu);
power_spectrum_cpu = abs(fft_cpu).^2;
cpu_fft_time = toc;
fprintf('CPU FFT时间: %.6f 秒\n', cpu_fft_time);
fprintf('GPU FFT时间: %.6f 秒\n', gpu_fft_time);
% 验证结果
power_spectrum_gpu_result = gather(power_spectrum_gpu);
fprintf('FFT结果误差: %.2e\n', norm(power_spectrum_cpu - power_spectrum_gpu_result) / norm(power_spectrum_cpu));
end
% 如果有GPU,运行GPU计算示例
if canUseGPU()
gpu_computing_demo();
gpu_signal_processing();
end
16.6 与其他语言的接口
16.6.1 调用Python代码
% 调用Python示例
function python_interface_demo()
% 检查Python环境
try
pyenv;
fprintf('Python环境已配置\n');
catch
fprintf('Python环境未配置,请先配置Python\n');
return;
end
% 调用Python内置函数
py_list = py.list({1, 2, 3, 4, 5});
py_sum = py.sum(py_list);
fprintf('Python list sum: %d\n', py_sum);
% 调用Python的NumPy
try
np = py.importlib.import_module('numpy');
% 创建NumPy数组
data_matlab = [1, 2, 3; 4, 5, 6];
data_numpy = np.array(data_matlab);
% 使用NumPy函数
numpy_mean = np.mean(data_numpy);
numpy_std = np.std(data_numpy);
fprintf('NumPy mean: %.4f\n', numpy_mean);
fprintf('NumPy std: %.4f\n', numpy_std);
% 比较MATLAB和NumPy结果
matlab_mean = mean(data_matlab, 'all');
matlab_std = std(data_matlab, 0, 'all');
fprintf('MATLAB mean: %.4f\n', matlab_mean);
fprintf('MATLAB std: %.4f\n', matlab_std);
catch ME
fprintf('NumPy not available: %s\n', ME.message);
end
end
% 调用Python机器学习
function python_ml_demo()
try
% 导入scikit-learn
sklearn = py.importlib.import_module('sklearn');
datasets = py.importlib.import_module('sklearn.datasets');
model_selection = py.importlib.import_module('sklearn.model_selection');
svm = py.importlib.import_module('sklearn.svm');
% 加载数据
iris = datasets.load_iris();
X = double(iris.data);
y = double(iris.target);
% 划分训练测试集
split_result = model_selection.train_test_split(iris.data, iris.target, ...
pyargs('test_size', 0.3, 'random_state', 42));
X_train = double(split_result{1});
X_test = double(split_result{2});
y_train = double(split_result{3});
y_test = double(split_result{4});
% 训练SVM模型
clf = svm.SVC(pyargs('kernel', 'rbf', 'C', 1.0));
clf.fit(X_train, y_train);
% 预测
y_pred = clf.predict(X_test);
y_pred_matlab = double(y_pred);
% 计算准确率
accuracy = sum(y_test == y_pred_matlab) / length(y_test);
fprintf('SVM分类准确率: %.4f\n', accuracy);
catch ME
fprintf('Scikit-learn not available: %s\n', ME.message);
end
end
% 运行Python接口示例
python_interface_demo();
python_ml_demo();
16.6.2 调用C/C++代码
% MEX文件示例
% 首先需要创建一个C文件,例如matrix_multiply.c
function create_mex_example()
% 创建C代码文件
c_code = sprintf([
'#include "mex.h"\n'...
'#include <string.h>\n'...
'\n'...
'void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])\n'...
'{\n'...
' double *A, *B, *C;\n'...
' int m, n, p;\n'...
' int i, j, k;\n'...
' \n'...
' /* 检查输入参数 */\n'...
' if (nrhs != 2) {\n'...
' mexErrMsgIdAndTxt("MyToolbox:matrix_multiply:nrhs", "Two inputs required.");\n'...
' }\n'...
' \n'...
' /* 获取输入矩阵尺寸 */\n'...
' m = mxGetM(prhs[0]);\n'...
' n = mxGetN(prhs[0]);\n'...
' p = mxGetN(prhs[1]);\n'...
' \n'...
' /* 检查矩阵尺寸兼容性 */\n'...
' if (n != mxGetM(prhs[1])) {\n'...
' mexErrMsgIdAndTxt("MyToolbox:matrix_multiply:incompatible", "Matrix dimensions incompatible.");\n'...
' }\n'...
' \n'...
' /* 获取输入数据指针 */\n'...
' A = mxGetPr(prhs[0]);\n'...
' B = mxGetPr(prhs[1]);\n'...
' \n'...
' /* 创建输出矩阵 */\n'...
' plhs[0] = mxCreateDoubleMatrix(m, p, mxREAL);\n'...
' C = mxGetPr(plhs[0]);\n'...
' \n'...
' /* 矩阵乘法 */\n'...
' for (i = 0; i < m; i++) {\n'...
' for (j = 0; j < p; j++) {\n'...
' C[i + j*m] = 0;\n'...
' for (k = 0; k < n; k++) {\n'...
' C[i + j*m] += A[i + k*m] * B[k + j*n];\n'...
' }\n'...
' }\n'...
' }\n'...
'}\n'
]);
% 写入C文件
fid = fopen('matrix_multiply.c', 'w');
fprintf(fid, '%s', c_code);
fclose(fid);
% 编译MEX文件
try
mex matrix_multiply.c;
fprintf('MEX文件编译成功\n');
% 测试MEX函数
A = randn(100, 50);
B = randn(50, 80);
% 使用MEX函数
tic;
C_mex = matrix_multiply(A, B);
mex_time = toc;
% 使用MATLAB内置函数
tic;
C_matlab = A * B;
matlab_time = toc;
% 比较结果
fprintf('MEX函数时间: %.6f 秒\n', mex_time);
fprintf('MATLAB内置函数时间: %.6f 秒\n', matlab_time);
fprintf('结果误差: %.2e\n', norm(C_mex - C_matlab, 'fro') / norm(C_matlab, 'fro'));
catch ME
fprintf('MEX编译失败: %s\n', ME.message);
end
end
% 运行MEX示例
create_mex_example();
16.7 高级绘图技术
16.7.1 动画制作
% 动画示例
function create_animations()
% 示例1:简单动画
figure('Position', [100, 100, 800, 600]);
% 准备数据
t = linspace(0, 4*pi, 100);
x = cos(t);
y = sin(t);
% 创建动画
h = plot(x(1), y(1), 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');
axis equal;
axis([-1.5, 1.5, -1.5, 1.5]);
grid on;
title('圆周运动动画');
% 添加轨迹
hold on;
trail = plot(x(1), y(1), 'b-', 'LineWidth', 1);
for i = 1:length(t)
% 更新点位置
set(h, 'XData', x(i), 'YData', y(i));
% 更新轨迹
set(trail, 'XData', x(1:i), 'YData', y(1:i));
% 更新标题
title(sprintf('圆周运动动画 - 时间: %.2f', t(i)));
drawnow;
pause(0.05);
end
% 示例2:3D动画
figure('Position', [100, 100, 800, 600]);
% 创建3D螺旋
t = linspace(0, 6*pi, 200);
x = cos(t);
y = sin(t);
z = t;
h3d = plot3(x(1), y(1), z(1), 'ro', 'MarkerSize', 8, 'MarkerFaceColor', 'r');
axis equal;
axis([-1.5, 1.5, -1.5, 1.5, 0, 6*pi]);
grid on;
title('3D螺旋动画');
xlabel('X'); ylabel('Y'); zlabel('Z');
hold on;
trail3d = plot3(x(1), y(1), z(1), 'b-', 'LineWidth', 2);
for i = 1:length(t)
set(h3d, 'XData', x(i), 'YData', y(i), 'ZData', z(i));
set(trail3d, 'XData', x(1:i), 'YData', y(1:i), 'ZData', z(1:i));
% 旋转视角
view(30 + i*2, 30);
drawnow;
pause(0.02);
end
end
% 创建GIF动画
function create_gif_animation()
% 准备数据
x = linspace(-2*pi, 2*pi, 100);
figure('Position', [100, 100, 800, 600]);
filename = 'wave_animation.gif';
for n = 1:50
% 创建波动
y = sin(x + n*0.2);
plot(x, y, 'b-', 'LineWidth', 2);
ylim([-1.5, 1.5]);
title(sprintf('正弦波动画 - 帧 %d', n));
xlabel('x');
ylabel('sin(x + t)');
grid on;
drawnow;
% 保存为GIF
frame = getframe(gcf);
im = frame2im(frame);
[imind, cm] = rgb2ind(im, 256);
if n == 1
imwrite(imind, cm, filename, 'gif', 'Loopcount', inf, 'DelayTime', 0.1);
else
imwrite(imind, cm, filename, 'gif', 'WriteMode', 'append', 'DelayTime', 0.1);
end
end
fprintf('GIF动画保存为: %s\n', filename);
end
% 运行动画示例
create_animations();
create_gif_animation();
16.7.2 交互式图形
% 交互式绘图示例
function interactive_plotting()
% 创建交互式绘图界面
fig = figure('Position', [100, 100, 1000, 700], 'Name', '交互式函数绘图器');
% 创建控件
amplitude_slider = uicontrol('Style', 'slider', 'Position', [50, 50, 200, 20], ...
'Min', 0.1, 'Max', 5, 'Value', 1, 'Callback', @update_plot);
frequency_slider = uicontrol('Style', 'slider', 'Position', [50, 80, 200, 20], ...
'Min', 0.1, 'Max', 10, 'Value', 1, 'Callback', @update_plot);
phase_slider = uicontrol('Style', 'slider', 'Position', [50, 110, 200, 20], ...
'Min', -pi, 'Max', pi, 'Value', 0, 'Callback', @update_plot);
% 创建标签
uicontrol('Style', 'text', 'Position', [260, 45, 80, 20], 'String', '振幅');
uicontrol('Style', 'text', 'Position', [260, 75, 80, 20], 'String', '频率');
uicontrol('Style', 'text', 'Position', [260, 105, 80, 20], 'String', '相位');
% 创建函数选择按钮
function_group = uibuttongroup('Position', [0.65, 0.05, 0.3, 0.15]);
sin_button = uicontrol(function_group, 'Style', 'radiobutton', ...
'Position', [10, 60, 100, 20], 'String', '正弦函数', 'Callback', @update_plot);
cos_button = uicontrol(function_group, 'Style', 'radiobutton', ...
'Position', [10, 35, 100, 20], 'String', '余弦函数', 'Callback', @update_plot);
tan_button = uicontrol(function_group, 'Style', 'radiobutton', ...
'Position', [10, 10, 100, 20], 'String', '正切函数', 'Callback', @update_plot);
% 设置默认选择
set(sin_button, 'Value', 1);
% 创建绘图区域
ax = axes('Position', [0.1, 0.3, 0.8, 0.6]);
% 初始化绘图
x = linspace(-2*pi, 2*pi, 1000);
line_handle = plot(ax, x, sin(x), 'b-', 'LineWidth', 2);
grid(ax, 'on');
xlabel(ax, 'x');
ylabel(ax, 'y');
title(ax, 'y = sin(x)');
% 回调函数
function update_plot(~, ~)
% 获取参数值
amp = get(amplitude_slider, 'Value');
freq = get(frequency_slider, 'Value');
phase = get(phase_slider, 'Value');
% 确定函数类型
if get(sin_button, 'Value')
y = amp * sin(freq * x + phase);
func_name = 'sin';
elseif get(cos_button, 'Value')
y = amp * cos(freq * x + phase);
func_name = 'cos';
else
y = amp * tan(freq * x + phase);
func_name = 'tan';
% 限制tan函数的显示范围
y(abs(y) > 10) = NaN;
end
% 更新绘图
set(line_handle, 'YData', y);
title(ax, sprintf('y = %.2f * %s(%.2f * x + %.2f)', amp, func_name, freq, phase));
% 自动调整坐标轴
if strcmp(func_name, 'tan')
ylim(ax, [-10, 10]);
else
ylim(ax, [-amp*1.2, amp*1.2]);
end
end
end
% 互动式数据探索器
function data_explorer()
% 创建示例数据
load('fisheriris'); % 载入鸢尾花数据集
fig = figure('Position', [100, 100, 1200, 800], 'Name', '数据探索器');
% 创建下拉菜单选择变量
var_menu = uicontrol('Style', 'popup', 'Position', [50, 750, 150, 30], ...
'String', {'萼片长度', '萼片宽度', '花瓣长度', '花瓣宽度'}, ...
'Callback', @update_visualization);
plot_type_menu = uicontrol('Style', 'popup', 'Position', [220, 750, 150, 30], ...
'String', {'散点图', '直方图', '箱线图', '小提琴图'}, ...
'Callback', @update_visualization);
% 创建标签
uicontrol('Style', 'text', 'Position', [50, 780, 150, 20], 'String', '选择变量:');
uicontrol('Style', 'text', 'Position', [220, 780, 150, 20], 'String', '选择图表类型:');
% 创建绘图区域
ax1 = axes('Position', [0.1, 0.4, 0.35, 0.35]);
ax2 = axes('Position', [0.55, 0.4, 0.35, 0.35]);
ax3 = axes('Position', [0.1, 0.05, 0.8, 0.25]);
% 初始化显示
update_visualization();
function update_visualization(~, ~)
var_idx = get(var_menu, 'Value');
plot_type = get(plot_type_menu, 'Value');
data = meas(:, var_idx);
var_names = {'萼片长度', '萼片宽度', '花瓣长度', '花瓣宽度'};
% 清除之前的图形
cla(ax1); cla(ax2); cla(ax3);
switch plot_type
case 1 % 散点图
% 散点图矩阵
for i = 1:4
for j = 1:4
subplot(4, 4, (i-1)*4 + j, 'Parent', fig);
if i == j
histogram(meas(:, i));
else
gscatter(meas(:, j), meas(:, i), species);
end
end
end
case 2 % 直方图
histogram(ax1, data, 20);
title(ax1, ['直方图 - ' var_names{var_idx}]);
xlabel(ax1, var_names{var_idx});
ylabel(ax1, '频次');
% 按种类分组的直方图
setosa_data = data(strcmp(species, 'setosa'));
versicolor_data = data(strcmp(species, 'versicolor'));
virginica_data = data(strcmp(species, 'virginica'));
hold(ax2, 'on');
histogram(ax2, setosa_data, 'FaceAlpha', 0.7, 'DisplayName', 'Setosa');
histogram(ax2, versicolor_data, 'FaceAlpha', 0.7, 'DisplayName', 'Versicolor');
histogram(ax2, virginica_data, 'FaceAlpha', 0.7, 'DisplayName', 'Virginica');
legend(ax2);
title(ax2, ['按种类分组 - ' var_names{var_idx}]);
case 3 % 箱线图
boxplot(ax1, data, species);
title(ax1, ['箱线图 - ' var_names{var_idx}]);
ylabel(ax1, var_names{var_idx});
% 显示统计信息
stats_text = sprintf('统计信息:\n均值: %.2f\n中位数: %.2f\n标准差: %.2f\n最小值: %.2f\n最大值: %.2f', ...
mean(data), median(data), std(data), min(data), max(data));
text(ax2, 0.1, 0.5, stats_text, 'Units', 'normalized', 'FontSize', 12);
set(ax2, 'XTick', [], 'YTick', []);
title(ax2, '描述性统计');
end
% 在底部显示相关性分析
correlation_matrix = corrcoef(meas);
imagesc(ax3, correlation_matrix);
colorbar(ax3);
set(ax3, 'XTick', 1:4, 'YTick', 1:4, 'XTickLabel', var_names, 'YTickLabel', var_names);
title(ax3, '变量间相关性矩阵');
colormap(ax3, 'cool');
end
end
16.7.3 App Designer
App Designer是MATLAB现代化的图形界面开发工具,类似于Python的Tkinter或Qt,但更加直观。
% 使用App Designer创建计算器应用
% 注意:这需要在App Designer环境中创建,这里展示核心逻辑
classdef CalculatorApp < matlab.apps.AppBase
% App Designer创建的计算器应用
properties (Access = public)
UIFigure matlab.ui.Figure
DisplayField matlab.ui.control.EditField
ButtonGrid matlab.ui.container.GridLayout
CurrentValue double = 0
PreviousValue double = 0
Operation char = ''
NewInput logical = true
end
methods (Access = private)
function results = calculateResult(app)
switch app.Operation
case '+'
results = app.PreviousValue + app.CurrentValue;
case '-'
results = app.PreviousValue - app.CurrentValue;
case '*'
results = app.PreviousValue * app.CurrentValue;
case '/'
if app.CurrentValue ~= 0
results = app.PreviousValue / app.CurrentValue;
else
results = NaN;
uialert(app.UIFigure, '除数不能为零!', '错误');
end
case '^'
results = app.PreviousValue ^ app.CurrentValue;
otherwise
results = app.CurrentValue;
end
end
function numberButtonPushed(app, event)
button = event.Source;
number = str2double(button.Text);
if app.NewInput
app.DisplayField.Value = button.Text;
app.NewInput = false;
else
app.DisplayField.Value = [app.DisplayField.Value button.Text];
end
app.CurrentValue = str2double(app.DisplayField.Value);
end
function operationButtonPushed(app, event)
button = event.Source;
if ~isempty(app.Operation) && ~app.NewInput
result = app.calculateResult();
app.DisplayField.Value = num2str(result);
app.CurrentValue = result;
end
app.PreviousValue = app.CurrentValue;
app.Operation = button.Text;
app.NewInput = true;
end
function equalsButtonPushed(app, event)
if ~isempty(app.Operation)
result = app.calculateResult();
app.DisplayField.Value = num2str(result);
app.CurrentValue = result;
app.Operation = '';
app.NewInput = true;
end
end
function clearButtonPushed(app, event)
app.DisplayField.Value = '0';
app.CurrentValue = 0;
app.PreviousValue = 0;
app.Operation = '';
app.NewInput = true;
end
end
methods (Access = private)
function createComponents(app)
% 创建UIFigure和组件
app.UIFigure = uifigure('Visible', 'off');
app.UIFigure.Position = [100 100 300 400];
app.UIFigure.Name = 'MATLAB 计算器';
% 创建显示屏
app.DisplayField = uieditfield(app.UIFigure, 'text');
app.DisplayField.Position = [20 340 260 40];
app.DisplayField.Value = '0';
app.DisplayField.FontSize = 16;
app.DisplayField.HorizontalAlignment = 'right';
app.DisplayField.Editable = 'off';
% 创建按钮网格
app.ButtonGrid = uigridlayout(app.UIFigure);
app.ButtonGrid.Position = [20 20 260 300];
app.ButtonGrid.ColumnWidth = {'1x', '1x', '1x', '1x'};
app.ButtonGrid.RowHeight = {'1x', '1x', '1x', '1x', '1x'};
% 创建按钮
buttons = {
'C', '±', '%', '÷';
'7', '8', '9', '×';
'4', '5', '6', '-';
'1', '2', '3', '+';
'0', '.', '=', '^'
};
for row = 1:5
for col = 1:4
btn = uibutton(app.ButtonGrid, 'push');
btn.Layout.Row = row;
btn.Layout.Column = col;
btn.Text = buttons{row, col};
btn.FontSize = 14;
% 设置回调函数
if ismember(btn.Text, {'0','1','2','3','4','5','6','7','8','9','.'})
btn.ButtonPushedFcn = createCallbackFcn(app, @numberButtonPushed, true);
elseif ismember(btn.Text, {'+','-','×','÷','^'})
btn.ButtonPushedFcn = createCallbackFcn(app, @operationButtonPushed, true);
elseif strcmp(btn.Text, '=')
btn.ButtonPushedFcn = createCallbackFcn(app, @equalsButtonPushed, true);
elseif strcmp(btn.Text, 'C')
btn.ButtonPushedFcn = createCallbackFcn(app, @clearButtonPushed, true);
end
end
end
end
end
methods (Access = public)
function app = CalculatorApp
% 构造函数
createComponents(app);
registerApp(app, app.UIFigure);
if nargout == 0
clear app
end
end
function delete(app)
% 析构函数
delete(app.UIFigure);
end
end
end
16.8 与其他语言对比
16.8.1 MATLAB vs Python
特性 | MATLAB | Python |
---|---|---|
矩阵运算 | 原生支持,语法简洁 | 需要NumPy,功能强大 |
绘图 | 内置强大绘图功能 | Matplotlib/Plotly等 |
社区 | 学术界广泛使用 | 开源社区庞大 |
成本 | 商业软件,需授权 | 免费开源 |
学习曲线 | 工程背景易上手 | 编程背景易上手 |
% MATLAB矩阵运算
A = [1 2; 3 4];
B = [5 6; 7 8];
C = A * B; % 矩阵乘法
D = A .* B; % 元素乘法
# Python等效代码
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
C = A @ B # 矩阵乘法
D = A * B # 元素乘法
16.8.2 MATLAB vs C++
特性 | MATLAB | C++ |
---|---|---|
开发速度 | 快速原型开发 | 需要更多代码 |
执行速度 | 解释执行,较慢 | 编译执行,很快 |
内存管理 | 自动管理 | 手动管理 |
数值计算 | 内置优化算法 | 需要第三方库 |
可移植性 | 需要MATLAB环境 | 编译后独立运行 |
% MATLAB快速实现FFT
x = randn(1024, 1);
X = fft(x);
plot(abs(X));
// C++需要更多代码实现相同功能
#include <fftw3.h>
#include <vector>
#include <complex>
std::vector<std::complex<double>> computeFFT(const std::vector<double>& input) {
// 需要大量代码实现FFT和绘图
// ...
}
16.9 最佳实践总结
16.9.1 代码组织
% 良好的代码组织示例
function result = data_analysis_pipeline(data_file)
% DATA_ANALYSIS_PIPELINE 数据分析流水线
%
% 输入:
% data_file - 数据文件路径
% 输出:
% result - 分析结果结构体
% 验证输入
validateInputs(data_file);
% 数据加载和预处理
data = loadData(data_file);
cleaned_data = preprocessData(data);
% 分析
stats = calculateStatistics(cleaned_data);
model = fitModel(cleaned_data);
% 可视化
figures = createVisualizations(cleaned_data, model);
% 组织结果
result = struct('statistics', stats, 'model', model, 'figures', figures);
% 生成报告
generateReport(result);
end
function validateInputs(data_file)
% 输入验证
if ~ischar(data_file) && ~isstring(data_file)
error('数据文件路径必须是字符串');
end
if ~exist(data_file, 'file')
error('文件不存在: %s', data_file);
end
end
function data = loadData(data_file)
% 数据加载逻辑
[~, ~, ext] = fileparts(data_file);
switch lower(ext)
case '.csv'
data = readtable(data_file);
case '.xlsx'
data = readtable(data_file);
case '.mat'
loaded = load(data_file);
data = loaded.data;
otherwise
error('不支持的文件格式: %s', ext);
end
end
16.9.2 性能优化技巧
% 性能优化示例
function optimized_computation()
% 坏的做法:动态增长数组
tic;
result_bad = [];
for i = 1:10000
result_bad = [result_bad, i^2]; % 每次重新分配内存
end
time_bad = toc;
% 好的做法:预分配数组
tic;
result_good = zeros(1, 10000); % 预分配
for i = 1:10000
result_good(i) = i^2;
end
time_good = toc;
% 最好的做法:向量化
tic;
result_best = (1:10000).^2; % 向量化运算
time_best = toc;
fprintf('动态增长: %.4f 秒\n', time_bad);
fprintf('预分配: %.4f 秒\n', time_good);
fprintf('向量化: %.4f 秒\n', time_best);
end
% 内存效率优化
function memory_efficient_processing()
% 处理大数据时的内存管理
% 使用单精度而非双精度(当精度允许时)
data_double = rand(1000, 1000); % 8 MB
data_single = single(rand(1000, 1000)); % 4 MB
% 及时清理不需要的变量
large_array = rand(10000, 10000);
processed = process_data(large_array);
clear large_array; % 释放内存
% 分块处理大数据
chunk_size = 1000;
total_size = 100000;
result = zeros(total_size, 1);
for i = 1:chunk_size:total_size
end_idx = min(i + chunk_size - 1, total_size);
chunk = generate_data_chunk(i, end_idx);
result(i:end_idx) = process_chunk(chunk);
clear chunk; % 清理临时数据
end
end
16.9.3 调试技巧
% 调试工具和技巧
function debugging_example()
% 使用断点和调试器
data = [1, 2, 3, NaN, 5, 6];
% 检查数据质量
if any(isnan(data))
warning('数据包含NaN值');
fprintf('NaN位置: %s\n', mat2str(find(isnan(data))));
end
% 使用try-catch处理错误
try
result = risky_computation(data);
catch ME
fprintf('错误发生在: %s\n', ME.stack(1).name);
fprintf('错误信息: %s\n', ME.message);
result = handle_error(data);
end
% 添加详细日志
log_computation_steps(data, result);
end
function result = risky_computation(data)
% 可能出错的计算
if any(data < 0)
error('输入数据不能包含负值');
end
result = sqrt(data);
end
function result = handle_error(data)
% 错误处理逻辑
data = abs(data); % 取绝对值
data(isnan(data)) = 0; % 替换NaN
result = sqrt(data);
end
function log_computation_steps(input_data, output_data)
% 记录计算步骤
fprintf('=== 计算日志 ===\n');
fprintf('输入数据大小: %s\n', mat2str(size(input_data)));
fprintf('输入数据范围: [%.2f, %.2f]\n', min(input_data), max(input_data));
fprintf('输出数据大小: %s\n', mat2str(size(output_data)));
fprintf('输出数据范围: [%.2f, %.2f]\n', min(output_data), max(output_data));
fprintf('计算完成时间: %s\n', datestr(now));
end
16.10 常见错误及解决方案
16.10.1 索引错误
% 常见索引错误及解决方案
function index_error_solutions()
A = rand(5, 5);
% 错误1:超出数组边界
try
value = A(6, 3); % 错误:超出边界
catch
fprintf('错误:数组索引超出边界\n');
% 解决方案:检查边界
[rows, cols] = size(A);
row_idx = min(6, rows);
col_idx = min(3, cols);
value = A(row_idx, col_idx);
end
% 错误2:使用0作为索引
try
value = A(0, 1); % 错误:MATLAB索引从1开始
catch
fprintf('错误:MATLAB索引从1开始,不是0\n');
% 解决方案
value = A(1, 1); % 正确
end
% 错误3:维度不匹配
B = rand(3, 4);
try
C = A + B; % 错误:维度不匹配
catch
fprintf('错误:矩阵维度不匹配\n');
% 解决方案:调整维度或使用兼容操作
if isequal(size(A), size(B))
C = A + B;
else
fprintf('无法直接相加,维度分别为 %s 和 %s\n', ...
mat2str(size(A)), mat2str(size(B)));
end
end
end
16.10.2 数据类型错误
% 数据类型相关错误
function data_type_solutions()
% 错误1:字符串和数值混合
data = {'apple', 'banana', 3, 'cherry'};
% 尝试对混合数据进行数值运算
numeric_data = [];
string_data = {};
for i = 1:length(data)
if isnumeric(data{i})
numeric_data = [numeric_data, data{i}];
else
string_data{end+1} = data{i};
end
end
fprintf('数值数据: %s\n', mat2str(numeric_data));
fprintf('字符串数据: %s\n', strjoin(string_data, ', '));
% 错误2:精度损失
x = 0.1 + 0.2;
if x == 0.3
fprintf('相等\n');
else
fprintf('不相等,x = %.17f\n', x);
% 解决方案:使用容差比较
tolerance = 1e-10;
if abs(x - 0.3) < tolerance
fprintf('在容差范围内相等\n');
end
end
end
16.11 项目实战综合案例
16.11.1 股票数据分析系统
% 股票数据分析系统
classdef StockAnalyzer < handle
properties
data
symbols
dates
prices
end
methods
function obj = StockAnalyzer()
obj.data = containers.Map();
end
function loadData(obj, filename)
% 加载股票数据
if exist(filename, 'file')
raw_data = readtable(filename);
obj.symbols = unique(raw_data.Symbol);
obj.dates = unique(raw_data.Date);
for i = 1:length(obj.symbols)
symbol = obj.symbols{i};
symbol_data = raw_data(strcmp(raw_data.Symbol, symbol), :);
obj.data(symbol) = symbol_data;
end
fprintf('成功加载 %d 只股票的数据\n', length(obj.symbols));
else
error('文件不存在: %s', filename);
end
end
function returns = calculateReturns(obj, symbol, period)
% 计算收益率
if ~obj.data.isKey(symbol)
error('未找到股票代码: %s', symbol);
end
stock_data = obj.data(symbol);
prices = stock_data.Close;
switch lower(period)
case 'daily'
returns = diff(log(prices));
case 'weekly'
returns = diff(log(prices(1:5:end)));
case 'monthly'
returns = diff(log(prices(1:22:end)));
otherwise
error('不支持的周期: %s', period);
end
end
function stats = analyzeVolatility(obj, symbol, window)
% 分析波动率
returns = obj.calculateReturns(symbol, 'daily');
% 滚动波动率
rolling_vol = zeros(length(returns) - window + 1, 1);
for i = 1:length(rolling_vol)
rolling_vol(i) = std(returns(i:i+window-1));
end
stats = struct();
stats.mean_volatility = mean(rolling_vol);
stats.max_volatility = max(rolling_vol);
stats.min_volatility = min(rolling_vol);
stats.rolling_volatility = rolling_vol;
end
function visualizeAnalysis(obj, symbol)
% 可视化分析结果
if ~obj.data.isKey(symbol)
error('未找到股票代码: %s', symbol);
end
stock_data = obj.data(symbol);
figure('Position', [100, 100, 1200, 800]);
% 价格走势
subplot(3, 1, 1);
plot(stock_data.Date, stock_data.Close, 'b-', 'LineWidth', 1.5);
title(sprintf('%s 股价走势', symbol));
ylabel('价格');
grid on;
% 成交量
subplot(3, 1, 2);
bar(stock_data.Date, stock_data.Volume, 'FaceColor', [0.7, 0.7, 0.7]);
title(sprintf('%s 成交量', symbol));
ylabel('成交量');
grid on;
% 收益率分布
subplot(3, 1, 3);
returns = obj.calculateReturns(symbol, 'daily');
histogram(returns, 50, 'FaceColor', [0.2, 0.6, 0.8]);
title(sprintf('%s 日收益率分布', symbol));
xlabel('收益率');
ylabel('频次');
grid on;
% 添加统计信息
mu = mean(returns);
sigma = std(returns);
text(0.7, 0.8, sprintf('均值: %.4f\n标准差: %.4f\n夏普比率: %.2f', ...
mu, sigma, mu/sigma*sqrt(252)), 'Units', 'normalized', ...
'BackgroundColor', 'white', 'EdgeColor', 'black');
end
function correlation_matrix = calculateCorrelation(obj, symbols)
% 计算股票间相关性
if nargin < 2
symbols = obj.symbols(1:min(10, length(obj.symbols)));
end
returns_matrix = [];
valid_symbols = {};
for i = 1:length(symbols)
if obj.data.isKey(symbols{i})
returns = obj.calculateReturns(symbols{i}, 'daily');
returns_matrix = [returns_matrix, returns];
valid_symbols{end+1} = symbols{i};
end
end
correlation_matrix = corrcoef(returns_matrix);
% 可视化相关性矩阵
figure;
imagesc(correlation_matrix);
colorbar;
colormap('cool');
set(gca, 'XTick', 1:length(valid_symbols), 'XTickLabel', valid_symbols);
set(gca, 'YTick', 1:length(valid_symbols), 'YTickLabel', valid_symbols);
title('股票收益率相关性矩阵');
% 添加数值标签
for i = 1:size(correlation_matrix, 1)
for j = 1:size(correlation_matrix, 2)
text(j, i, sprintf('%.2f', correlation_matrix(i,j)), ...
'HorizontalAlignment', 'center', 'Color', 'white');
end
end
end
end
end
% 使用示例
function stock_analysis_demo()
% 创建分析器实例
analyzer = StockAnalyzer();
% 生成示例数据(实际使用中应该加载真实数据)
generate_sample_data();
% 加载数据
analyzer.loadData('sample_stock_data.csv');
% 分析特定股票
symbol = 'AAPL';
% 计算收益率
returns = analyzer.calculateReturns(symbol, 'daily');
fprintf('%s 平均日收益率: %.4f%%\n', symbol, mean(returns)*100);
% 分析波动率
vol_stats = analyzer.analyzeVolatility(symbol, 30);
fprintf('%s 平均30日波动率: %.4f\n', symbol, vol_stats.mean_volatility);
% 可视化分析
analyzer.visualizeAnalysis(symbol);
% 计算相关性
symbols = {'AAPL', 'GOOGL', 'MSFT', 'TSLA'};
corr_matrix = analyzer.calculateCorrelation(symbols);
fprintf('相关性分析完成\n');
end
function generate_sample_data()
% 生成示例股票数据
symbols = {'AAPL', 'GOOGL', 'MSFT', 'TSLA', 'AMZN'};
dates = datetime('2020-01-01'):caldays(1):datetime('2023-12-31');
dates = dates(~isweekend(dates)); % 排除周末
all_data = table();
for i = 1:length(symbols)
symbol = symbols{i};
n_days = length(dates);
% 生成模拟价格数据(几何布朗运动)
S0 = 100 + randn * 20; % 初始价格
mu = 0.08 / 252; % 年化收益率转日收益率
sigma = 0.2 / sqrt(252); % 年化波动率转日波动率
returns = normrnd(mu, sigma, n_days-1, 1);
log_prices = cumsum([log(S0); returns]);
prices = exp(log_prices);
% 生成成交量数据
base_volume = 1e6 + randn * 2e5;
volumes = abs(base_volume + randn(n_days, 1) * 1e5);
% 创建数据表
symbol_data = table();
symbol_data.Symbol = repmat({symbol}, n_days, 1);
symbol_data.Date = dates';
symbol_data.Close = prices;
symbol_data.Volume = volumes;
all_data = [all_data; symbol_data];
end
% 保存数据
writetable(all_data, 'sample_stock_data.csv');
fprintf('示例数据已生成并保存到 sample_stock_data.csv\n');
end
更多推荐
所有评论(0)