···························································· 第5 章 chapter5 MATLAB科学计算 本章学习目标 ● 了解低级输入/输出函数的使用方法; ● 了解常用最优化问题处理的基本函数和方法; ● 掌握多项式运算、线性和非线性方程组的求解方法; ● 掌握格式化数据文件输入/输出函数的使用方法; ● 熟练掌握数值、符号微积分函数的使用方法; ● 熟练掌握常用插值和拟合函数的操作方法。 在解决实际和科研工作问题中,用户往往会遇到各种各样的数学计算,如多项式处 理、方程组求解、微积分、插值与拟合等,这些计算常常难以通过手工运算获得精确的结 果,必须借助计算机编制相应的程序来实现。此外,在进行数据处理前,用户也需通过一 定的方法将数据读入MATLAB,并对数据分布有基本的了解。MATLAB为解决此类问 题提供了一个很好的计算平台,同时提供了相当丰富的数学运算,使得用户可以更加专 注于对实际数学问题的求解。 5.1 数据读写 在实际工作中,经常需要将外部数据和文件读入到MALTAB中,或将运算结果写 入磁盘文件中。根据文件性质,可将其分为格式化数据(如TXT、XLS、CSV 等)和低级 文件(如二进制文件)。下面将分别介绍各类常用文件的数据读写函数。 5.1.1 文本文件 MATLAB中可用于读取文本文件数据的函数包括textread和textscan函数,其中 textread函数接收参数为文件名(或文件路径),且返回结果需要根据数据中列的数量指 定相应数量的接收变量;而textscan函数则必须用fopen函数打开,即接收的参数为文件 句柄,结果则返回到一个指定的单元数组中。下面将分别介绍。 2 12 ◆M ATLAB 程序设计与综合应用 1.textread函数 MATLAB提供了textread函数用于读取文本文件中的数据,调用格式如下。 [A,B,C,...]=textread(filename,format) 以指定的format将数据从文件filename读入到A、B、C等变量中,直到整个文件读 取完毕。将filename和format输入指定为字符向量或字符串标量。textread对于读取 已知格式的文本文件非常有用,也可处理固定格式文件和任意格式文件。 textread 可对输入中的字符组进行匹配和转换。每个输入字段都定义为一组连续延伸的非 空白字符,这些字符延伸到下一个空白字符或分隔符,或者到达最大字段宽度时停止。 重复的分隔符为有效字符,而重复的空白字符视为一个字符。 [A,B,C,...]=textread(filename,format,N) 读取数据,重用格式设定符format中指定的格式N 次,其中N 是大于零的整数。如 果N 小于零,textread将读取整个文件。 [...]=textread(...,param,value,...) 使用param/value对组自定义textread。 format 输入 指定为字符向量或字符串向量,用于确定返回参数的数量和类型。返回参数的数量 是format的内容所指示的项目数。format支持部分转换设定符和C语言fscanf例程约 定。format中的空白字符将被忽略。 textread函数的format参数选项如表5-1所示,param 参数选项如表5-2所示。 表5-1 textread函数中format参数选项 格 式操 作输 出 字面值 忽略匹配的字符。例如,在Dept后跟一个数字(用作部门编 号)的文件中,要跳过Dept并仅读取该数字,需在格式设定 符format中使用Dept 无 %d 读取有符号整数值双精度数组 %u 读取整数值双精度数组 %f 读取浮点值双精度数组 %s 读取以空白或分隔符分隔的文本字符向量元胞数组 %q 读取带双引号的文本,并忽略引号字符向量元胞数组 %c 读取包括空白在内的字符字符数组 %[...] 读取包含方括号中指定的字符的最长字符组字符向量元胞数组 第◆5 章 MATLAB 科学计算2 13 续表 格 式操 作输 出 %[^...] 读取包含非方括号中指定字符的最长非空字符组字符向量元胞数组 %*... 忽略*指定的匹配字符无输出 %w... 读取w指定的字段宽度。%f格式支持%w.pf,其中w是字段 宽度,p是精度 表5-2 textread函数中param 参数选项 参 数数 值作 用 bufsize 正整数指定最大字符创长度(字节),默认4095 commentstyle MATLAB 忽略%后的字符 commentstyle c 忽略#后的字符 commentstyle C++ 忽略//后的字符 delimiter 1个或多个字符元素间的分隔符 emptyvalue 空值空值替代符,默认为0 endofline 单个字符或\r\n 行结束符 expchars 指数字符默认为e或E headerlines 正整数忽略文件开始的行数 whitespace ‘’ 空格 \b 退格 \n 换行 \r 回车 \t Tab键 【例5-1】 用textread函数读取数据。 (1)用格式控制符读取所有字段。%Chapter5_1.dat的第一行如下: Sally Level1 12.34 45 Yes >> [names, types, x, y, answer]=textread('Chapter5_1.dat',… '%s %s %f %d %s', 1) names= 'Sally' types= 'Level1' x= 12.3400 y= 2 14 ◆M ATLAB 程序设计与综合应用 45 answer= 'Yes' (2)用格式控制符读取数据,但忽略数值。 >> [names, types, y, answer]=textread('Chapter5_1.dat',… '%9c %6s %*f %2d %3s', 1) names= Sally types= 'Level1' y= 45 answer= 'Yes' (3)用格式控制符读取数据,但忽略匹配字符。 >> [names, typenum, x, y, answer]=textread('Chapter5_1.dat',… '%s Level%d %f %d %s', 1) names= 'Sally' typenum= 1 x= 12.3400 y= 45 answer= 'Yes' (4)用格式控制符读取数据,但指定值给空值,Chapter5_2.txt文件内的数据如下: 1,2,3,4,,6 7,8,9,,11,12 >> data=textread('Chapter5_2.txt', '', 'delimiter', ',', 'emptyvalue', NaN); data= 1 2 3 4 NaN 6 7 8 9 NaN 11 12 2.textscan函数 MATLAB提供的textscan函数也可用于从文本文件或字符串中读取数据,调用格 式如下。 C=textscan(fileID,formatSpec) 第◆5 章 MATLAB 科学计算2 15 将已打开的文本文件中的数据读取到元胞数组C。该文本文件由文件标识符fileID 指示。使用fopen可打开文件并获取fileID 值。完成文件读取后,请调用fclose(fileID) 来关闭文件。 textscan 尝试将文件中的数据与formatSpec中的转换设定符匹配。textscan函数在整个文 件中按formatSpec重复扫描数据,直至formatSpec找不到匹配的数据时才停止。 C=textscan(fileID,formatSpec,N) 按formatSpec读取文件数据N 次,其中N 是一个正整数。要在N 个周期后从文件 读取其他数据,请使用原fileID再次调用textscan进行扫描。如果通过调用具有相同文 件标识符(fileID)的textscan恢复文件的文本扫描,则textscan将在上次终止读取的点 处自动恢复读取。 C=textscan(chr,formatSpec) 将字符向量chr中的文本读取到元胞数组C 中。从字符向量读取文本时,对 textscan的每一次重复调用都会从开头位置重新开始扫描。要从上次位置重新开始扫 描,需要指定position输出参数。 textscan 尝试将字符向量chr中的数据与formatSpec中指定的格式匹配。 C=textscan(chr,formatSpec,N) 按formatSpecN 次,其中N 是一个正整数。 C=textscan(___,Name,Value) 使用一个或多个Name,Value对组参数以及上述语法中的任何输入参数来指定 选项。 [C,position]=textscan(___) 在扫描结束时返回文件或字符向量中的位置作为第二个输出参数。对于文件,该值 等同于调用textscan后再运行ftell(fileID)所返回的值。对于字符向量,position指示 textscan读取了多少个字符。 【例5-2】 用textscan函数读取文本文件数据。 (1)从字符变量中读取字符串。 >> str='0.41 8.24 3.57 6.24 9.27'; >> C=textscan(str,'%f'); >> celldisp(C) C{1}= 0.4100 2 16 ◆M ATLAB 程序设计与综合应用 8.2400 3.5700 6.2400 9.2700 (2)读取字符,并确定保留小数位数。 %%3.1f 表示读取的字符宽度为3 位,小数点后保留1 位;%*1d 表示跳过其他位数 >> C=textscan(str,'%3.1f %*1d'); >> celldisp(C) C{1}= 0.4000 8.2000 3.5000 6.2000 9.2000 (3)读取不同数值类型,数据Chapter5_3.txt内容如下: 09/12/2005 Level1 12.34 45 1.23e10 inf Nan Yes 5.1+3i 10/12/2005 Level2 23.54 60 9e19 -inf 0.001 No 2.2-.5i 11/12/2005 Level3 34.90 12 2e5 10 100 No 3.1+.1i >> fileID=fopen('Chapter5_3.txt'); >> C=textscan(fileID,'%s %s %f32 %d8 %u %f %f %s %f'); >> fclose(fileID); >> cellplot(C); %图5-1 图5-1 textscan函数读取数据后用cellplot显示结果 (4)读取数据Chapter5_3.txt中不同数值类型,但忽略Level字符。 >> fileID=fopen('Chapter5_3.txt'); >> C=textscan(fileID,'%s Level%d %f32 %d8 %u %f %f %s %f'); >> fclose(fileID); C{2} ans= 1 2 3 (5)仅读取数据Chapter5_3.txt中部分字符而忽略其余内容(整行)。 >> fileID=fopen('Chapter5_3.txt'); >> dates=textscan(fileID,'%s %*[^\n]'); 第◆5 章 MATLAB 科学计算2 17 >> fclose(fileID); dates{1} ans= '09/12/2005' '10/12/2005' '11/12/2005' (6)指定数据Chapter5_4.txt中分隔符和空值替代值,内容如下: 1, 2, 3, 4, , 6 7, 8, 9, , 11, 12 >> fileID=fopen('Chapter5_4.txt'); >> C=textscan(fileID,'%f %f %f %f %u8 %f',… 'Delimiter',',','EmptyValue',-Inf); >> fclose(fileID); >> column4=C{4}, column5=C{5} column4= 4 -Inf column5= 0 11 (7)读取数据Chapter5_5.txt中用户自定义空值,并忽略注释行,内容如下: abc, 2, NA, 3, 4 // Comment Here def, na, 5, 6, 7 >> fileID=fopen('Chapter5_5.txt'); >> C=textscan(fileID,'%s %n %n %n %n','Delimiter',',',… 'TreatAsEmpty',{'NA','na'},'CommentStyle','//'); >> fclose(fileID); celldisp(C) C{1}{1}= abc C{1}{2}= def C{2}= 2 NaN C{3}= NaN 5 C{4}= 3 6 2 18 ◆M ATLAB 程序设计与综合应用 C{5}= 4 7 (8)将数据Chapter5_6.txt中多个分隔符处理为1个,内容如下: 1,2,3,,4 5,6,7,,8 >> fileID=fopen('Chapter5_6.txt'); >> C=textscan(fileID,'%f %f %f %f','Delimiter',',',… 'MultipleDelimsAsOne',1); >> fclose(fileID); celldisp(C) C{1}= 1 5 C{2}= 2 6 C{3}= 3 7 C{4}= 4 8 (9)读取数据Chapter5_7.txt中字符,但忽略引号,内容如下: "Smith, J.","M",38,71.1 "Bates, G.","F",43,69.3 "Curie, M.","F",38,64.1 "Murray, G.","F",40,133.0 "Brown, K.","M",49,64.9 % %q 读取被双引号括起来的字符,%*q 忽略被引号括起来的字符;%*d 忽略整数 >> fileID=fopen('Chapter5_7.txt','r'); >> C=textscan(fileID,'%q %*q %*d %f','Delimiter',','); >> fclose(fileID); celldisp(C) C{1}{1}= Smith, J. C{1}{2}= Bates, G. C{1}{3}= Curie, M. C{1}{4}= Murray, G. 第◆5 章 MATLAB 科学计算2 19 C{1}{5}= Brown, K. C{2}= 71.1000 69.3000 64.1000 133.0000 64.9000 (10)读取Chapter5_8.txt中数值数据,内容如下: Student_ID | Test1 | Test2 | Test3 1 91.5 89.2 77.3 2 88.0 67.8 91.0 3 76.3 78.1 92.5 4 96.4 81.2 84.6 % 读取字段名 >> fileID=fopen('Chapter5_7.txt'); >> formatSpec='%s'; >> N=4; >> C_text=textscan(fileID,formatSpec,N,'Delimiter','|'); % 读取数值,但结果为4 个单独的列 >> C_data0=textscan(fileID,'%d %f %f %f') % 读取数值,按数据类型分类存储 % C_data1=textscan(fileID,'%d %f %f %f','CollectOutput',1) % 关闭文件 >> fclose(fileID); C_data0= [4x1 int32] [4x1 double] [4x1 double] [4x1 double] 5.1.2 Excel 文件 微软的Excel文件是用户日常工作中经常用到的数据存储、编辑和管理工具。为此, MATLAB提供了xlsread和xlswrite函数分别用于Excel表格数据的读写,分别介绍 如下。 1.xlsread函数 xlsread函数可将Excel表格中的数据导入到MATLAB工作空间,调用格式如下。 num=xlsread(filename) 读取名为filename的MicrosoftExcel电子表格工作表中的第一个工作表,并在一个 2 20 ◆M ATLAB 程序设计与综合应用 矩阵中返回数值数据。 num=xlsread(filename,sheet) 读取指定的工作表。 num=xlsread(filename,xlRange) 从工作簿的第一个工作表的指定范围内读取数据。使用Excel范围语法,例如 A1:C3。 num=xlsread(filename,sheet,xlRange) 读取指定的工作表和范围。 num=xlsread(filename,sheet,xlRange,'basic') 在basic导入模式下读取电子表格中的数据。如果计算机未安装Windows版 Excel,或者正在使用MATLABOnlineTM ,xlsread会自动在basic导入模式下运行,该模 式支持XLS、XLSX、XLSM、XLTX和XLTM 文件。如果不指定所有参数,请使用空字 符向量作为占位符,例如,num=xlsread(filename,'','','basic')。 [num,txt,raw]=xlsread(___) 还使用先前语法中的任何输入参数,在元胞数组txt中返回文本字段,在元胞数组 raw中返回数值数据和文本数据。 ___=xlsread(filename,-1) 打开一个Excel窗口以便按交互方式来选择数据。选择工作表,将鼠标光标拖放到 所需范围上,然后单击“确定”按钮。只有安装了MicrosoftExcel软件的Windows计算 机才支持此语法。 [num,txt,raw,custom]=xlsread(filename,sheet,xlRange,'',processFcn) 其中processFcn是函数句柄。读取电子表格,对数据调用processFcn,并在数组 num 中以数值数据的形式返回最终结果。xlsread函数在元胞数组txt中返回文本字段、 在元胞数组raw中返回数值和文本数据,并在数组custom 中返回processFcn的第二个 输出。xlsread 函数不会更改电子表格中存储的数据。只有安装了Excel软件的 Windows计算机才支持此语法。 2.xlswrite函数 xlswrite函数可将MATLAB工作空间内的数据写入Excel表格中,调用格式如下。 xlswrite(filename,A) 将矩阵A 写入MicrosoftExcel电子表格工作簿filename中的第一个工作表,从单 元格A1开始写入。