【实验】实验一 MATLAB环境与运算基础20211008

本文仅供学习和复习使用。 题目源于岑冠军老师,答案参考自相关课件,另外借以markdown排版成此文。由于本人水平有限且时间不够充裕,故难免有错漏或不当之处,如有建议或批评还请联系[email protected],谢谢!

目录

  • 实验一 MATLAB环境与运算基础
    • 一、实验目的
    • 二、实验原理
    • 三、实验内容

实验一 MATLAB环境与运算基础

@Copyright 华南农业大学 数学与信息学院 数学系 主讲与制作:岑冠军


一、实验目的

  • 掌握 MATLAB环境与基本操作;
  • 掌握MATLAB常见数据类型的创建、表示和引用;
  • 熟悉MATLAB数据类型的各种运算与常用函数;
  • 熟悉导入外部数据文件创建变量。

二、实验原理

  • MATLAB环境与基本操作:命令窗口、WorkSpace、当前文件夹和帮助命令与窗口;
  • MATLAB数据类型及其对应的常用操作函数:数值型、字符与字符串、日期和时间、分类数组、表、结构体和元胞数组;
  • MATLAB运算:线性代数计算,+(加),-(减),*(乘),/(除),^(乘幂);点运算,.*(点乘),./(点除),.^(点乘幂);逻辑运算;
  • MATLAB常用函数:初等数学函数,取整函数和矩阵操作运算的常用函数reshape、diag、sum、mean等;
  • 读取外部文件数据的函数:readmatrix,readtable,readvars,readcell,及其选项设置。

三、实验内容

  1. 利用MATLAB的帮助系统分别查询inv、plot、max、round等函数的功能和用法。
help("inv");
help("plot");
help("max");
help("round");
  1. 求下列表达式的值:
    (1) z 1 = 2 sin ⁡ ( 85 ° ) 1 + e 2 z_1 = \frac{2\sin(85\degree)}{1 + e^2} z1=1+e22sin(85°)
    (2) z 2 = 1 2 ln ⁡ ( x + 1 + x 2 ) z_2 = \frac{1}{2} \ln(x + \sqrt{1 + x^2}) z2=21ln(x+1+x2 ),其中 x = [ 2 1 + 2 i − 0.45 5 ] x = \begin{bmatrix} 2 & 1 + 2i\\ -0.45 & 5 \end{bmatrix} x=[20.451+2i5]
% (1)
z1 = 2 * sin(85/180*pi) / (1 + exp(2))  % 0.2375
% (2)
x = [2, 1+2j; -0.45, 5];
z2 = 1/2 .* log(x + sqrt(1 + x.^2))  % omitted
clearvars;
  1. 写出完成下列操作的命令:
    (1) 建立3阶单位矩阵;
    (2) 建立5*5随机矩阵 A A A,其元素为[100,200]范围内的随机整数;
    (3) 产生均值为1,方差为0.2的50个正态分布的随机数;
    (4) 产生和 A A A同样大小的全1矩阵;
    (5) 将矩阵 A A A的对角线元素加30;
    (6) 从矩阵 A A A提取对角线元素,并以这些元素构成对角阵 B B B
% (1)
% eye() 以产生单位矩阵(Identity Matrix)
eye(3)
% (2)
% 可以调用更高级的函数如 randint (其在笔者所用的 2020b 版中已改为 randi)
% 示例如下,但是为了锻炼编程思维,仍建议使用最本质的 rand() 和 round() 组合
% rand() 以产生指定维度的 [0,1] 之间的随机数矩阵
% round() 以向下取整
% A = randi([100 200],[5 5])
A = round(rand([5 5]) .* (200 - 100) + 100)
% (3)
% randn() 以产生指定维度的标准正态分布的随机数矩阵
randn([50 1]) * sqrt(0.2) + 1
% (4)
% ones() 以产生指定维度的全 1 矩阵
ones(size(A))
% (5)
A + eye(5).*30
% (6)
% diag() 对矩阵取对角元为向量,或对向量转换为以其作为对角元的矩阵
B = diag(diag(A))
clearvars
  1. 已知: A = [ 12 34 − 4 34 7 87 3 65 7 ] , B = [ 1 3 − 1 2 0 3 3 − 2 7 ] A = \begin{bmatrix} 12 & 34 & -4\\ 34 & 7 & 87\\ 3 & 65 & 7 \end{bmatrix}, B = \begin{bmatrix} 1 & 3 & -1\\ 2 & 0 & 3\\ 3 & -2 & 7 \end{bmatrix} A=12343347654877,B=123302137,求下列表达式的值:
    (1) C 11 = A + 6 B C_{11} = A + 6 B C11=A+6B C 12 = A − B + I C_{12} = A - B + I C12=AB+I
    (2) C 21 = A B C_{21} = A B C21=AB C 22 = A C_{22} = A C22=A的元素与 B B B的对应元素相乘;
    (3) C 31 = A 3 C_{31} = A^3 C31=A3 C 32 = A C_{32} = A C32=A的每个元素立方;
    (4) C 41 = A B − 1 C_{41} = A B^{-1} C41=AB1 C 42 = A − 1 B C_{42} = A^{-1} B C42=A1B
    (5) C 51 C_{51} C51 C 52 C_{52} C52分别为 A A A B B B按列和按行合并后的矩阵;
    (6) C 6 C_6 C6 A A A的第2、3行,第2、3列,与 B B B的第1,2行,第1,2列,按列合并后的矩阵。
% 初始化矩阵 A, B
A = [12, 34, -4; 34, 7, 87; 3, 65, 7];
B = [1, 3, -1; 2, 0, 3; 3, -2, 7];

% (1)
C11 = A + 6.*B
C12 = A - B + eye(size(A))
% (2)
C21 = A * B % 矩阵乘法
C22 = A .* B % 矩阵对应元素作乘法
% (3)
C31 = A^3 % 矩阵乘幂
C32 = A.^3 % 矩阵对应元素乘幂
% (4)
C41 = A / B
C42 = A \ B % 取 A 的逆 A^{-1}
% (5)
C51 = [A; B] % ; 换行
C52 = [A, B]
% (6)
C6 = [A(2:3, 2:3); B(1:2, 1:2)] % 切片索引,从 1 开始
clearvars
  1. 金庸的武侠小说引人入胜,本题第一行代码可以提取《天龙八部》的文本,请回答以下问题:
    (1) 小说《天龙八部》一共有多少个自然段(提示:段落之间通常用回车符’\r’分隔)?
    (2) 《天龙八部》男主角有段誉与乔峰之争,请问该小说分别包含段誉和乔峰的段落有多少个?
    (3) 段誉与乔峰同时出现的段落有多少个?
% extractFileText() 读取文本得到一个连续的字符串
str = extractFileText("tianlongbabu.txt",'Encoding','UTF-8');
% (1)
strspl = strsplit(str, '\r'); % split by '\r'
% size() 获取字符串个数,可以对比 size(str) 看看
size(strspl)
% (2)
num_of_duan = sum(contains(strspl, "段誉"))
% (或许大概可能该考虑萧峰...!?
% contains() 确定字符串中是否有指定字符串(更专业的说法是"是否含有指定模式",正则表达式里经常提及)
% 若不含则是 0 ,包含为 1 ,返回的是一个只有 0 和 1 的向量,通过 sum() 获取满足条件的段落数
num_of_qiao = sum(contains(strspl, "乔峰") | contains(strspl, "萧峰"))
% (3)
% 关于 && || 和 & | 的区别可以越读这篇博客 https://blog.csdn.net/jiejianmin2666/article/details/78148533
num_of_duan_qiao = sum(contains(strspl, "段誉") & (contains(strspl, "乔峰") | contains(strspl, "萧峰")))
clearvars
  1. 创建以下变量并计算:
    (1) 创建分类数组存储被观测者的国籍:uk,us,no,au,uk,us,us;
    (2) 创建结构体Student,存储以下数据:
    Name Sex Age Score
    Liming F 30 80,78,92,84
    (3) 在student中添加学生:Yangle, M, 30, [85,68,87,92]
    (4) 计算学生Liming与Yangle的平均成绩
% (1)
nationality = ["uk", "us", "no", "au", "uk", "us", "us"]
% (2)
% 此数据结构似乎是将若干个指针放在数组里,用索引可以找到对应指针
% 数组里的每个指针又指向结构体,存放着各种类型的数据
% 与 C/C++ 不同的是这里的结构体并不需要定义,更加自由
Student(1).name = "Liming";
Student(1).sex = "F";
Student(1).age = 30;
Student(1).score = [80, 78, 92, 84];
Student(1)
% (3)
% 因为要添加,所以 (2) 中已经将结构体创建在数组里
Student(2).name = "Yangle";
Student(2).sex = "M";
Student(2).age = 30;
Student(2).score = [85, 68, 87, 92];
Student(2)
% (4)
% 取 score 对应的向量,调用 mean() 函数
mean_li = mean(Student(1).score)
mean_yang = mean(Student(2).score)
clearvars
  1. 文件e17.txt存储了一个矩阵的数据,请做以下操作:
    (1) 读取文件e17.txt的数据到MATLAB中,并存入矩阵 A A A中;
    (2) 提取A矩阵,生成以下子矩阵:
    A 11 A_{11} A11 A A A的第1,2行,第1,2,3列; A 12 A_{12} A12 A A A的第1,2行,第4,5列;
    A 13 A_{13} A13 A A A的第1,2行,第6列; A 21 A_{21} A21 A A A的第3行,第1,2,3列;
    A 22 A_{22} A22 A A A的第3行,第4,5列; A 23 A_{23} A23 A A A的第3行,第6列;
    (3) 将 A A A矩阵转换成的元胞数组,对应元素与(2)题中提取的子矩阵相同。
% (1)
% readmatrix() 以矩阵形式读取
A = readmatrix("e17.txt")
% (2)
% 通过切片索引取出元素
A11 = A(1:2, 1:3)
A12 = A(1:2, 4:5)
A13 = A(1:2, 6)
A21 = A(3, 1:3)
A22 = A(3, 4:5)
A23 = A(3, 6)
% (3)
% 通过 {} 构建元胞数组
% 或调用更高级的函数 mat2cell
% cell_A = mat2cell(A,[2,1],[3,2,1])
cell_A = {
    A11, A12, A13;
    A21, A22, A23
    }
clearvars
  1. 文件Animals2.csv记录了65个物种的躯干(body,kg)和脑(brain,g)的重量,请做以下操作:
    (1) 以MATLAB表的类型导入Animals2.csv中的数据,指定行名为动物名称,指定变量名为body和brain,并指定它们的单位,展示前三行数据;
    (2) 在表中添加变量ratio,其值等于脑与躯干的重量比并取自然对数后的值;
    (3) 提取Human、Cow和African elephant的数据记录;
    (4) 提取ratio超过3的数据记录?
% (1)
% readtable() 读取表格
animal2 = readtable("Animals2.csv", "ReadRowNames",true)
% 类似于矩阵的切片索引,只不过列可以用列名(字符串)来表示
animal2((1:3), "body")
animal2((1:3), "brain")
% (2) 
% 注意运用点除 ./
animal2.ratio = log(animal2.brain ./ animal2.body)
% (3)
% 仍然是类似于矩阵的切片索引,单个字符串索引如 (1) ,这里为多个字符串索引
animal2({'Human', 'Cow', 'African elephant'}, :)
% (4)
% find() 查找满足条件的位置,返回 0 1 向量
animal2.ratio((find(animal2.ratio > 3)))
clearvars
  1. 文件detail.csv记录了某餐厅8月份的点餐情况,请做以下操作:
    (1) 以MATLAB表的类型导入detail.csv中的detail_id(流水号),order_id(订单号),dishes_name(菜名),counts(数量),amounts(单价),place_order_time(下单时间)等变量,其中文本数据用string类型;
    (2) 将place_order_time变量转换成datetime类型,格式为yyyy-MM-dd HH:mm:ss,并展示前三行数据记录;
    (3) 计算周一、周二、…、周日的平均消费额。
% (1)
% 初始化
detail = readtable("detail.csv", "TextType", "string");
detail = detail(:, {'detail_id', 'order_id', 'dishes_name', 'counts', 'amounts', 'place_order_time'})
% (2)
% 这里发现下单时间一栏的原始数据并不符合预期格式,一般处理方式为人工查找不符合预期的位置
% 但为了更好地锻炼数据处理能力,笔者提供更一般的思路
split_placeordertime = split(detail.place_order_time, '/'); % split() 分割
split_time = split_placeordertime(:, 3)
for i = 1 : size(split_time)
    s = char(split_time(i)); % string -> char
    s = sprintf("%010s", s); % 填充 0 以使得 s 的长度为 10
    split_time(i) = s;
end
split_placeordertime(:, 3) = split_time;
detail.place_order_time = join(split_placeordertime, '/'); % join() 执行 split() 的逆操作
% 转换为 datatime 类型
place_of_time_format = datetime(detail.place_order_time(1:10037), "InputFormat", "yyyy/MM/ddHH:mm:ss")
% (3)
detail.consumption = detail.counts .* detail.amounts;
detail.weekday = weekday(detail.place_order_time) % weekday() 处理的很巧妙
cons = zeros(1, 7);
for i = 1 : 7
    index = find(detail.weekday==i);
    cons(1, i) = sum(detail.consumption(index)) / size(detail.consumption(index), 1);
end
cons % 展示结果
clearvars

你可能感兴趣的:(MATLAB,matlab)