注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

notes

@-@

 
 
 

日志

 
 
 
 

Some MATLAB tips   

2008-11-25 20:43:49|  分类: matlab |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

tip1: 数据文件的批处理。用MATLAB程序实现将某一文件夹下的所有数据文件内容(或某些部分)读入内存,以备后续处理之用。

例如:要读入 C:\data 文件夹下的所有数据文件并合并为一个矩阵,下面给出相应代码:

cd(’C:\data‘);
AllName=struct2cell(dir);       %得到上述文件夹下的所有文件名%逐个读入文件
[m,n]=size(AllName);
for i=3:n   %前两个不是文件名
    name=Allname{1,i};
    Imdata=importdata(name);
    if i==3
        data=Imdata;
    else
        data=[data,Imdata];
    end
    clear Imdata
end

tip2:启动MATLAB时,自动设定所需的搜寻路径和工作目录。

如果在每一次启动MATLAB后都要设定所需的搜寻路径,将是一件很麻烦的事。有两种方法,可以使MATLAB启动后 ,即可载入使用者定义的搜寻路径:  

1.MATLAB的预设搜寻路径是定义在matlabrc.m(在D:\MATLAB7\toolbox\local之下),MATLAB每次启动后,即自动执行此档案。因此你可以直接修改matlabrc.m ,以加入新的目录于搜寻路径之中。  

2.MATLAB在执行matlabrc.m时,同时也会在预设搜寻路径中寻找 startup.m,若此档案存在,则执行其所含的命令。因此我们可将所有在MATLAB启动时必须执行的命令(包含更改搜寻路径的命令),放在此档案 中。但是MATLAB7中将startup.m  更名另存另存为了startupsav.m。这时只需将其改回原名 startup.m 保存即可。例如:想让MATLAB启动后将工作目录(默认为 D:\MATLAB\work)改变为 E:\WorkSpace\MATLAB ,按如下步骤操作即 可:                                                                                                                                                                                   
            ①,找到文件 startupsav.m (在D:\MATLAB7\toolbox\local之下),在最后一行添加
                    cd  E:\WorkSpace\MATLAB;
            ②,保存退出,将文件名改为 startup.m即可;或者直接另存为 startup.m。

3.利用 path 指令扩展搜索路径:path(path,'c:\mydir');

4.在 MATLAB 命令窗键入 pathtool; ;或者在Matlab命令窗口的菜单 File->Set Path 进行设置。

每次MATLAB遇到一个命令(例如test)时,其处置程序为:  

1.将test视为使用者定义的变数。

2.若test不是使用者定义的变数,将其视为永久常数 。

3.若test不是永久常数,检查其是否为目前工作目录下的M档案。

4.若不是,则由搜寻路径寻找是否有test.m的档案。

5.若在搜寻路径中找不到,则MATLAB会发出哔哔声并印出错误讯息。  

tip3:打开matlab就出现如下的提示
        The element type "name" must be terminated by the matching end-tag "</name>".
        Could not parse the file: d:\matlab7\toolbox\ccslink\ccslink\info.xml.

解决办法如下:
找到d:\matlab7\toolbox\ccslink\ccslink\info.xml 这个文件,用写字板打开,找到里面有一行这样的
                       <name>Link for Code Composer Studio?/name>
应该是在第七行或者附近!把这句的/name>改成</name>,即把此行改为
                       <name>Link for Code Composer Studio?/<name>
再保存一下这个文件。这样修改后,应当不会有问题了。

tips4.关于MATLAB中内联函数,匿名函数,嵌套函数,M-文件函数等的效率问题.
 
从根本上来说,,MATLAB函数分为两类匿名函数(Anonymous Function)和M-文件函数(M-File Function)。下面,我们从一个例子来说明各类函数地应用与效率比较。
 
问题描述:现在我要画一个数值算法的稳定区域,即要求出在复平面中矩形区域[-2,2;-30;30]内所有能使方程a(u)*x2+b(u)*x+c(u)=0的跟的模小于1的u的值并画图。
 
以匿名函数写的程序如下:
clear all
tic
% 系数;去掉分母后可以认为与原方程同解
a = @(u) exp(u)*(-1+exp(u)-2*u+u*exp(u));
b = @(u) -exp(u)*(-1-2*u+exp(2*u));
c = @(u) exp(2*u)*(-1+exp(u)-u);
% 求根公式
root1 = @(u) -b(u)+sqrt(b(u)^2-4*a(u)*c(u));
root2 = @(u) -b(u)-sqrt(b(u)^2-4*a(u)*c(u));
% 变量初始化
t = 1;
Result=zeros(400*600,1);
% 遍历区域【-2:2;-30:30】;若点满足条件,则存储该值
for ii = -2:0.01:2;
    for jj = -30:0.1:30;       
        if (   abs(root1(ii + i*jj)) < abs(2*a(ii + i*jj))...
            && abs(root2(ii + i*jj)) < abs(2*a(ii + i*jj))  )
            Result(t) = ii + i*jj;
            t = t+1;
        end
    end
end
plot(Result,'.')
toc
 
运行结果:Elapsed time is 86.485000 seconds.
 
 
M-文件函数和嵌套函数程序:
function R1 = root12(u)
% 用求根公式计算方程的两个根
R1 = [ (-b(u)+sqrt(b(u)^2-4*a(u)*c(u)))/(2*a(u)+eps),
       (-b(u)-sqrt(b(u)^2-4*a(u)*c(u)))/(2*a(u)+eps) ]; 
function funa = a(u)   % Subfuntion
% 计算系数a(u)
    funa = exp(u)*(-1+exp(u)-2*u+u*exp(u));
end 
function funb = b(u)   % Subfunction
% 计算系数b(u)
    funb = -exp(u)*(-1-2*u+exp(2*u));
end  
function func = c(u)   % Subfunction
% 计算系数c(u)
    func = exp(2*u)*(-1+exp(u)-u);
end
end
 
clear all
tic
% 变量初始化
t = 1;
Result=zeros(400*600,1);
% 遍历区域【-2:2;-30:30】;若点满足条件,则存储该值
for ii = -2:0.01:2;
    for jj = -30:0.1:30;       
        if (   min(abs(root12(ii + i*jj))<1) ~=0  )
            Result(t) = ii + i*jj;
            t = t+1;
        end
    end
end
plot(Result,'.')
toc
 
运行结果:Elapsed time is 36.328000 seconds.
 
 
不用函数直接把算式写在M脚本里:
clear all;
tic
% 变量初始化
t = 1;
Result=zeros(400*600,1);
% 遍历区域【-2:2;-30:30】;若点满足条件,则存储该值
for ii = -2:0.01:2;
    for jj = -30:0.1:30;       
        %if (   abs(root1(ii + i*jj)) < abs(2*a(ii + i*jj))...
        %    && abs(root2(ii + i*jj)) < abs(2*a(ii + i*jj))  )
        if (    abs( exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj)))...
                + sqrt(((-exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj))))^2)...
                - 4*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))*(exp(2*(ii + i*jj))*(-1+exp(ii + i*jj)-(ii + i*jj)))))...
                < abs( 2*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj))))...
            &&  abs( exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj)))...
                - sqrt(((-exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj))))^2)...
                - 4*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))*(exp(2*(ii + i*jj))*(-1+exp(ii + i*jj)-(ii + i*jj)))))...
                < abs( 2*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))))
            Result(t) = ii + i*jj;
            t = t+1;
        end
    end
end
plot(Result,'.')
toc
 
运行结果:Elapsed time is 26.578000 seconds.
 
结果是很明显,直接将公式写在M文件里比使用函数要快的多。这主要是因为调用函数时系统要做额外的进栈出栈和传 值工作。这里没有考虑内联函数(Inline Function),因为他是基于符号计算的,效率比匿名函数要低一些。但是将公式直接写在M文件了,程序的可读性,重用性,可维护性都大大降低。折中的 办法也只能是对于调用次数很多的复杂的公式还是要做一个M文件函数的,当然如果掉用次数小公式本身又比较简单,用匿名函数也是自然的事情。
 
 
tips5.关于上述代码的另一点小tip.
 
这一点是无意中发现的。将上述程序做如下小改动(细致点看哦); 
clear all;
tic
% 变量初始化
t = 1;
%Result=zeros(400*600,1);
% 遍历区域【-2:2;-30:30】;若点满足条件,则存储该值
for ii = -2:0.01:2;
    for jj = -30:0.1:30;       
        %if (   abs(root1(ii + i*jj)) < abs(2*a(ii + i*jj))...
        %    & abs(root2(ii + i*jj)) < abs(2*a(ii + i*jj))  )
        if (    abs( exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj)))...
                + sqrt(((-exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj))))^2)...
                - 4*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))*(exp(2*(ii + i*jj))*(-1+exp(ii + i*jj)-(ii + i*jj)))))...
                < abs( 2*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj))))...
            &&  abs( exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj)))...
                - sqrt(((-exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj))))^2)...
                - 4*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))*(exp(2*(ii + i*jj))*(-1+exp(ii + i*jj)-(ii + i*jj)))))...
                < abs( 2*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))))
            Result(t) = ii + i*jj;
            t = t+1;
        end
    end
end
plot(Result,'.')
toc
 
看出来没有?其实就是把 %Result=zeros(400*600,1); 关掉了;把 && 改为 &.
 
接下来,看你的 Current Directory 窗口 上方有一个键上面有个小对号√
 
点一下进去回出现下面的界面,ZMY_StableArea_2.m 就是我们上面的脚本的文件名:
 
 
看到了吧!其实这是一个Code Check工具,一些不是太好的做法它会提示修改。例如上面的程序,如果所提示的第31行不做修改的话,运行结果为: Elapsed time is 63.984000 seconds. 这远远比做修改后的26.578000 seconds要慢!这其实容易理解,一个是为数组元素动态分配内存,一种是预分配,显然预分配要快一些,这是典型的空间换时间的做法。

1,MALAB 译于矩阵实验室(MATrix LABoratory),是用来提供通往LINPACK 和EISPACK 矩阵软件包接口的。后来它渐渐发展成了通用科技计算图视交互系统和程序语言。

2,命令窗口中, Esc    清除当前行的全部内容。

3,[例3]矩阵元素输入
         >>B(1,2)=3;B(4,4)=6;B(4,2)=11
         B =
                0     3     0     0
                0     0     0     0
                0     0     0     0
                0    11     0     6
这其实是创建矩阵的一种方式,矩阵维数维已给坐标的最大值。例如本例,行坐标最大为 B(4,4)和B(4,2)中所给 4,列坐标最大值为 B(4,4) 所给 4,所以创建矩阵维数为4X4。

5,注意:MATLAB 是区分字母的大小写的!

6,Who 和Whos 这两个指令的作用都是列出在MATLAB 工作间中已经驻留的变量名清单。不过,Whos 在给出变量名的同时还给出它们的维数及性质。

7,在MATLAB 工作内存中驻留着几个由系统本身在启动时定义的变量(如下表)称为永久变量(Permanent variables)或称为预定义变量(Predefined variables)。

系统预定义变量
eps 计算机的最小正数,在PC机上为 2^(-52)
pi 圆周率π 的近似值3.14159265358979
inf 或 Inf 无穷大
NaN 不定量
i,j 虚数单位定义i = j = (?1)^(1/2)
flops 浮点运算次数,用于统计计算量

说明:1 它们是在MATLAB 启动时自定义的;
            2 它们不会被清除内存变量指令clear 所清除;
            3 他们可以重新定义为其他值但用clear 可清除重定义值恢复预定义值。

8,help  elfun     -- 列出所有基本函数
      help  目录名  -- 显示指定目录中的所有命令及其函数

9,lookfor 指令可以根据用户提供的完整或不完整的关键词去搜索出一组与之有关的指令
      [例2]查找有关傅里叶变换的指令
              lookfor fourier
lookfor 指令的机制:对MATLAB 中的每个M 文件注释区的第一行进行扫描,一旦发现包含要查询的字符串就显示出来。

10,利用指令reshape 创建数值矩阵
av=1:12 %产生12 个元素的行向量av 以%开头的是注释行
bm=reshape(av,3,4) %利用向量av 创建3× 4 矩阵bm
av =
1 2 3 4 5 6 7 8 9 10 11 12
bm =
1 4 7 10
2 5 8 11
3 6 9 12

11,利用指令diag 产生对角阵
ar=rand(4,4) %产生4 × 4 的0-1 均匀分布随即矩阵ar
d=diag(ar) %用矩阵的主对角线元素形成向量d
D=diag(d) %用向量d 构成对角矩阵D
ar =
0.9501 0.8913 0.8214 0.9218
0.2311 0.7621 0.4447 0.7382
0.6068 0.4565 0.6154 0.1763
0.4860 0.0185 0.7919 0.4057
d =
0.9501
0.7621
0.6154
0.4057
D =
0.9501 0 0 0
0 0.7621 0 0
0 0 0.6154 0
0 0 0 0.4057

12,[例] 矩阵标识
x=[1 2 3 4 5]    %产生1× 5 向量
x =
1 2 3 4 5
l=x<=3              %标出小于等于3 的元素的位置
l =
1 1 1 0 0
x=x(l)                 %获得元素不超过3 的子向量
x =
1 2 3

13,inv(A)    矩阵求逆
         f(A)        求A 的各个元素的函数值

14,在MATLAB 中,inv 指令不很有用。MATLAB 推荐:尽量使用除运算少用逆运算!

15,rand('seed',12);      %选定随机种子,即rand()算法中的起始值;目的是可重复产生同一随机数。
例如:

>> rand('seed',12);rand

ans =

    0.1549

>> rand('seed',12);rand

ans =

    0.1549

如果不用seed,每次的随机数均不同:

>> rand

ans =

    0.6048

>> rand

ans =

    0.5040

16,MATLAB 在设计求逆函数inv 时,采用的是Gauss 消去法。而左除运算解恰定方程时,并不求逆而是直接采用Gauss 消去法求解,有效地减少了残差,所以即便在高条件数下也能得到较好的结果。

17,矩阵除法解超定方程组的方法
(1) 求正则方程(Normal equations) (ATA)x = AT b 的解.
(2) 用Householder 变换(Householder transformation)直接求原超定方程的最小二乘解。
由于第二种方法采用的是正交变换,根据最小二乘理论可知:第二种方法所得的解的准确性可靠性都比第一种方法好得多。MATLAB 解超定方程组用的就是第二种方法。

18,矩阵除法解欠定方程组
欠定方程的解是不唯一的。用除法运算所得的解有两个重要特征:(1) 在解中至多有Rank(A)个非零元素;(2) 它是这类型解中范数最小的一个.

19,多项式p( x ) = a0xn + a1xn-1 + ... + an-1x + an , 用以下系数行向量表示p= [ a0, a1, ... ,an-1, an  ] 。

20,MATLAB 约定:多项式系数用行向量表示,一组根用列向量表示。

21,P=polyfit(x,y,n)     用n 阶多项式拟合x,y 向量给定的数据

22,有效拟合的区间性图示(用[0,2.5]区间数据拟合曲线拟合[0,5]区间数据)
x=0:0.1:5;
x1=0:0.1:2.5
y=erf(x); %误差函数
y1=erf(x1);
p=polyfit(x1,y1,6)
f=polyval(p,x);
plot(x,y,'bo',x,f,'r-')
axis([0,5,0,2])
legend('拟合曲线','原数据线')


23,多项式非线性函数求根 r=roots(p)
例 p=[1 2 3 4];
r=roots(p)
r =
-1.6506
-0.1747 + 1.5469i
-0.1747 - 1.5469i

24,单变量非线性方程求解(单变量函数求零点)
            z=fzero('fname',x0,tol,trace)
其 中,fname 是待求根的函数名;x0 为搜索的起点,一个函数可能有多个根,但fzero 函数只给出离x0 最近的那个根;tol 控制结果的相对精度,缺省时取tol=eps;trace 指定迭代信息是否在运算中显示,为1 时显示,为0 时不显示,缺省时trace=0。

25,一般非线性方程(组)求解
此部分内容已超出MATLAB 的"主包"范围,它需要用到MATLAB 的优化(Optimization)工具包。但由于非线性方程组是常用遇到的一类数学问题,因此在此一并简单介绍对于一般非线性方程组F(X)=0 其数值解X的求解指令  
X=fsolve('fname',X0)
其中,fname 是待求根的函数名;x0 是对解的初始猜测值。

26,ode45 比ode23 的积分分段少而运算速度快

27,执行外部程序
感叹号(!)是MATLAB 的一个特殊命令。它指示其后的命令为操作系统命令,利用 ! 可以在不退出MATLAB 的情况下执行其它程序或操作系统命令。这是很有用的。
例如:>> !notepad  xxx.m
则用记事本打开 xxx.m 文件。

28,读二进制数据文件
fread 函数可读取二进制的数据文件。例如:将wzs.dat 中的所有数据无符号字符读入并写入到矩
阵a 中,
fid=fopen('penny.dat','r');
a=fread(fid);
ststus=fclose(fid);
fread 函数还可以有两个参数,用于控制读出数据数目和每个数据的精度。例如:将wzs.dat 的前100 个数据无符号字符读入并写入矩阵a中,
fid=fopen('wzs.dar','r');
a=fread(fid,100);
ststus=fclose(fid);
或 读入wzs.dat 的前100 个数据并组合成10 阶方阵
fid=fopen('wzs.dar','r');
a=fread(fid,[10 10]);
ststus=fclose(fid);

29,写二进制数据文件
MATLAB 的write 函数与fread 函数相对应,其功能是按照指定的数据精度将矩阵中的元素写入到文件中并返回写入数据的个数。例如,创建一个含100 个字节的二进制文件,即包含了5 阶魔方矩阵的25 个元
素,每个元素以4 字节的整数方式存储。在变量count 中得到fwrite 函数的返回值25:
fwriteid=fopen('magic.bin','w');
count=fwrite(fwriteid,magic(5),'integer*4');
status=fclose(fwriteid);

30,taylor(f,n,a) --函数f 对符号变量x 或最接近字母x 的符号变量,在a点的n-1 阶泰勒多项式(n 缺省时值为6,a 缺省值为0)。
例如:

taylor(sin(x))
ans =x-1/6*x^3+1/120*x^5

f=log(x)
s=taylor(f,4,2)
f =log(x)
s =log(2)+1/2*x-1-1/8*(x-2)^2+1/24*(x-2)^3

31,一个非常简便的画图指令
设表达式f 中只有一个符号变量,比如x,则 ezplot(f,xmin,xmax)画出以x 为横坐标的曲线f,x 在[xmin
xmax]内缺省值为,xmin=-2Pi,xmax=2Pi.

ezplot(sin(2*x))
ezplot(sin(2*x),-pi/2,pi/2)

32,plot 绘图线性:   

o或者O 圆圈
x或者X 叉号
+ 加号

33,添加图例   legend('sin(x)','cos(x)');

34,fplot 函数可自适应的对函数进行采样能更好反映函数的变化规律。
函数格式 fplot(fname,lims,tol),其中fname 为函数名,以字符串形式出现; lims 为变量取值范围;tol 为相对允许误差,其默认值为2e-3。
例如:
fplot('sin(x)',[0 2*pi],'-+')
fplot('[sin(x),cos(x)]',[0 2*pi],1e-3,'*')
fplot('cos(tan(pi*x))',[0,1],1e-4)

可见,在坐标0.5 附近无限振荡时采样点十分密集。若采用等间隔采样不能真实反映函数变化规律。

35,pause 函数
当程序运行时为了查看程序的中间结果或观看输出的图形,有时需要暂停程序的执行,这时可以使用pause 函数。其调用格式为:
pause(延迟秒数)
如果省略延迟时间,直接使用pause ,则将暂停程序直到用户按任一键后程序继续执行。

36,~=    不等于

37, MATLAB 在函数调用上有一个与众不同之处::函数所传递参数数目的可调性.。凭借这一点,一个函数可完成多种功能在调用函数时,MATLAB 用两个永久变量nargin 和nargout 分别记录调用该函数时的输入实参的个数。只要在函数文件中使用这两个变量,就可以准确地知道该函数文件被调用时的输入输出参数个数,从而决定函数如何进行 处理。
函数文件examp.m:
function fout=charray(a,b,c)
if nargin==1
fout=a;
else if nargin==2
fout=a+b;
else if nargin==3
fout=(a*b*c)/2;
end

-------------------------
  评论这张
 
阅读(1735)| 评论(1)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018