 
    Varargin的用法和例子(摘自MATLAB.Sky)
1. 基础例子
在写《用Matlab演示Parzen窗法》的时候,我还不知道怎样在m中设计可变参数函数。后来阅读一些m自带函数源码时发现了它的秘密,只要将最后一个参数设置为varargin,就可以实现。
例如,写了一个函数:function test(varargin),那么在这个函数里,varargin就是一个cell数组,它包含了用户输入的参数。下面是一个例子:
functiontest(varargin)
disp(['nargin is ' num2str(nargin)]);
for v=1:numel(varargin)
      disp(['varargin{' num2str(v) '} class is 'class(varargin{v})]);
end 
完全就是使用cell数组的方法来处理用户输入的个数不定的参数,如果我们这样调用这个函数:
>> test()
会得到结果:
nargin is 0
表示用户输入参数个数为0个,就是没有输入参数。
如果这样调用:
>>test(1,'a',uint8(32),'123456');
会得到结果:
nargin is 4
varargin{1} class is double
varargin{2} class is char
varargin{3} class is uint8
varargin{4} class is char 
表示用户输入了4个参数,第一个是double类型,第二个是char类型,第三个是uint8类型,第四个也是char类型。
也就是说,只要把函数的参数列表的最后一个参数写成varargin,就可以在函数内部以访问cell数组的方式来获取可变参数的信息。
有了这个varargin,我们就可以改写原来那个Parzen函数了。原来的Parzen函数的最后一个参数是函数句柄,用来传入窗函数,但是也可不指定窗函数,那么Parzen会自动使用正态窗,但是那时不知道使用varargin,于是在使用默认的正态窗时,最后一个参数依然得指定,输入一个[]。这样也凑合,能用,但毕竟不优雅。
这几天忙于做最简单的雷达信号仿真(不知道为什么在最繁忙的时候事情总是最多),需要使用Parzen窗法估计接收信号的概率密度函数,以使用贝叶斯来确定门限。趁此机会把Parzen函数改写了,如下:
function p=Parzen(xi,x,h1,varargin)
%xi为样本,x为概率密度函数的自变量的取值,
%h1为样本数为1时的窗宽,
%最后一个参数为窗函数句柄,
%不指定则使用正态窗
%返回x对应的概率密度函数值
n=numel(varargin);
if 0==n
    %若没有指定窗的类型,就使用正态窗函数
    f=@(u)(1/sqrt(2*pi))*exp(-0.5*u.^2);
elseif 1==n
    if isa(varargin{1},'function_handle')
        f=varargin{1};
    else
        disp('The last param must befunction handle');
        p=[];
        return;
    end
else
    disp('too many param');
    p=[];
    return;
end;
N=size(xi,2);
hn=h1/sqrt(N);
[X Xi]=meshgrid(x,xi);
p=sum(f((X-Xi)/hn)/hn)/N; 
2. 其他例子1
function[xyinput_in,xybase_in,input,base] = ParseInputs(varargin)
iptchecknargin(4,4,nargin,mfilename);%%%是在判断输入参数为4吗?
xyinput_in =varargin{1};%%%varargin{1}什么意思啊?
xybase_in =varargin{2};
if size(xyinput_in,2) ~= 2 || size(xybase_in,2)~= 2 error(message('images:cpcorr:cpMatrixMustBeMby2'))
end
%%size(xyinput_in,2)%是不是等于size(varargin{2},2)哪有具体是什么意思啊?
function[xyinput_in,xybase_in,input,base] = ParseInputs(varargin)
iptchecknargin(4,4,nargin,mfilename);%%是在判断输入参数为4吗?是!
xyinput_in =varargin{1};%%varargin{1}什么意思啊? 取4个参数中第一个参数赋给xyinput_in ,varargin是元胞xybase_in = varargin{2};
if size(xyinput_in,2) ~= 2 || size(xybase_in,2)~= 2 error(message('images:cpcorr:cpMatrixMustBeMby2'))
end%size(xyinput_in,2)是不是等于size(varargin{2},2),哪有具体是什么意思啊?
size(xyinput_in,2) 等于size(varargin{1},2),你看错了,另外size(a,2)指的是矩阵a的列数


3. 其他例子2
Matlab有非常多的内嵌函数和工具箱函数用到了varargin。比如最常见的plot函数,除了x,y是数据意外,剩下的都需指定 属性名称(PropertyName)及其 属性值(PropertyValue)。例如:
x = -pi:pi/10:pi;
y = tan(sin(x)) -sin(tan(x));
Plot(x,y,'--rs','LineWidth',2,'MarkerEdgeColor','k',…
'MarkerFaceColor','g','MarkerSize',10);
当函数形参过多的时候,使用varargin定义函数形参的形式是非常必要的。但是帮助文件言之不详,而且普通的调用方法无法实现报错功能。在查阅众多内嵌函数后,这里给大家以一个例子说明各种数据类型:字符串、数值、变量的用法。
本文最有价值的在于两个内嵌函数(help都help不到哦)的使用:
internal.stats.parseArgs internal.stats.getParamVal
对每个属性赋值,若调用lrh函数时没有添加某个属性,则自动为默认值这个函数的意义就在于不需要对着varargin元胞一个一个对比、赋值了。报错功能:凡是属性值包含字符串的属性,都需要用此函数检查是否用户输入的属性值不包含在属性全部属性值中。
函数调用脚本
X=1:20;
Y=60:-1:41;
result=lrh(x,y,'Algorithm','+','U',4,'Sqornot','false');
function result=lrh(x,y,varargin)
%% varargin示例函数
% x,y为长度为l的两个数值向量
% 用于计算result=f(x,y)
% Algorithm包含加、减、乘、除四种运算
% a为x前系数,b为y前系数,如result=ax+by默认为1.
% u为截距项,默认为长度为l的零向量
% sqornot为是否开方,属性值为true 或者 false
%% 设置默认属性、属性值
paramNames ={'Algorithm','A','B','U','Sqornot'};
vU=zeros(length(x),1);
defaultsValue ={'+',1,1,vU,'false'};
%% 对每个属性赋值,若调用lrh函数时没有添加某个属性,则自动为默认值
[vAlgorithm, vA,vB, vUU, vSqornot]...
=internal.stats.parseArgs(paramNames,defaultsValue,varargin{:});
%% 报错功能:凡是属性值包含字符串的属性,都需要用internal.stats.getParamVal检查是否用户输入的属性值不包含在属性全部属性值中
AlgorithmNames ={'+','-','*','/'};
vAlgorithm =internal.stats.getParamVal(vAlgorithm,AlgorithmNames,...
'''Algorithm''');
SqornotNames ={'true','false'};
vSqornot =internal.stats.getParamVal(vSqornot,SqornotNames,...
'''Sqornot''');
%% 主函数
vUU=zeros(length(x),1)+vUU;
switch vAlgorithm
case'+'
switch vSqornot
case 'true'
result=sqrt(vA*x+vB*y+vUU);
case 'false'
result=vA*x+vB*y+vUU;
end
case '-'
switch vSqornot
case 'true'
result=sqrt(vA*x-vB*y-vUU);
case 'false'
result=vA*x-vB*y-vUU;
end
case '*'
switch vSqornot
case 'true'
result=sqrt((vA*x).*(vB*y).*vUU);
case 'false'
result=(vA*x).*(vB*y).*vUU;
end
case '/'
switch vSqornot
case 'true'
result=sqrt((vA*x)./(vB*y)./vUU);
case 'false'
result=(vA*x)./(vB*y)./vUU;
end
end
4. 其他例子3
C语言中可以通过参数的个数和数据类型来区分同名函数,实现函数的重载。matlab的函数重载是通过检查函数调用时输入输出的项数来实现。
nargin和nargout分别返回它所在函数当前被调用时实际输入的项数
nargchk()检查输入的参数个数是否符合指定的范围:
msgstr=nargchk(minargs,maxargs,numargs)
msgstr=nargchk(minargs,maxargs,numargs,'string')
其中,minargs和maxargs合法的最大值最小值,numargs为求得的输入项的项数,可直接为函数nargin。如果输入变量个数超出范围,则返回错误信息;如果变量个数在范围内则返回空矩阵。
例:实现两个数相加或者三个数相乘
function B =addd(varargin)
% varargin是matlab内部变量,cell型,依次存储函数的所有输入变量
% 如add(A1, A2, A3), 则 varargin{1} = A1,varargin{2} = A2, varargin{3} = A3
% nargin同样也是matlab内部变量, 为函数输入变量的个数
%如果变量个数小于2大于3,则报错
error(nargchk(2,3,nargin));
if nargin == 2
A1= varargin{1};
A2= varargin{2};
B=A1+A2;
else
A1= varargin{1};A2=varargin{2};
A3=varargin{3};
B=A1*A2*A3;
end ;
>> addd(1)
Error using addd(line 2)
Not enough inputarguments.
>> addd(1,2,3,4)
Error using addd(line 2)
Too many inputarguments.
>>addd(7,2,3)
ans =
42

自己总结的画图例子
function Sa=AExample_P321varargin(varargin)
if nargin>2%%如果输入变量大于2
Sa=0;%%%面积就为0
return;%%强制退出函数
elseif nargin==0
s='b';%%%%一种颜色蓝色
r=1;%%%半径的大小
elseif nargin==1
if isa(varargin{1},'char')%%%输入的只有颜色char类
r=1;
s=varargin{1};%%将颜色varargin{1}赋予给s
elseif isa(varargin{1},'double')%%%输入的只有半径double类
s='b';
r=varargin{1};
end
else%%%%nargin==2
    r=varargin{1};
    s=varargin{2};
end
t=0:pi/10:2*pi;
x=r*exp(i*t);
if nargout==0
figure(1)
set(figure(1),'color','w')
plot(x,s,'linewidth',2)
hold on
plot(x,'rp','markersize',10)
xlabel('Real')
ylabel('Image')
hold off
else
Sa=pi*r^2;%%%%%%圆的面积
fill(real(x),imag(x),'b')
end
commandwindows输入:AExample_P321varargin() 或者
AExample_P321varargin(3) 或者
AExample_P321varargin('g') 或者
AExample_P321varargin(3,'b') 或者

画图例子2
function varargout=AExample_P323varargin(varargin)
Vin=length(varargin);%%%%%或者Vin=numel(varargin);也行!!!!
Nin=Vin+1;
error(nargchk(0,Nin,nargin));%%%输入的变量个数必须大于等于0,和小于等于Nin
if nargout>6
    error('too many input variables')
end
n=0:pi/10:2*pi;
if Vin==0
        r1=1;
        r2=2;
        x1=r1*exp(i*n);x2=r2*exp(i*n);
        plot(x1,'b','linewidth',3),hold on,plot(x1,'rp','markersize',12)
        plot(x2,'g','linewidth',3),plot(x2,'bo','markersize',12),hold off
elseif Vin==1
        r1=varargin{1};
        r2=2;
        x1=r1*exp(i*n);x2=r2*exp(i*n);
        plot(x1,'b','linewidth',3),hold on,plot(x1,'rp','markersize',12)
        plot(x2,'g','linewidth',3),plot(x2,'bo','markersize',12),hold off
elseif Vin==2
        r1=varargin{1};
        r2=varargin{2};
        x1=r1*exp(i*n);x2=r2*exp(i*n);
        plot(x1,'b','linewidth',3),hold on,plot(x1,'rp','markersize',12)
        plot(x2,'g','linewidth',3),plot(x2,'bo','markersize',12),hold off
elseif Vin==3
        r1=varargin{1};
        r2=varargin{2};
        s=varargin{3};%%%%颜色
        x1=r1*exp(i*n);x2=r2*exp(i*n);
        plot(x1,s,'linewidth',3),hold on,plot(x1,'rp','markersize',12)
        plot(x2,s,'linewidth',3),plot(x2,'bo','markersize',12),hold off
elseif Vin>3
        r1=varargin{1};
        r2=varargin{2};
        s=varargin{3};
        x1=r1*exp(i*n);x2=r2*exp(i*n);
        plot(x1,s,varargin{4:end}),hold on,plot(x1,'rp','markersize',12)
        plot(x2,s,varargin{4:end}),plot(x2,'bo','markersize',12),hold off
end
varargout{1}=real(x1);
varargout{2}=real(x2);
varargout{3}=imag(x1);
varargout{4}=imag(x2);
varargout{5}=pi*r1^2;
varargout{6}=pi*r2^2;
       TEST:
[xx,yy]=AExample_P323varargin()  或者
AExample_P323varargin(5)
AExample_P323varargin(5,4)
 AExample_P323varargin(5,4,'c')
 AExample_P323varargin(5,4,'y','linewidth',10)

自制的基于遗传算法的例子(以GEAT toolbox为例子)
function [Bestfval,Independentvariables]=GEATsolvefun(varargin)
error(nargchk(9,9,nargin));%%%不输入9个变量就是错误的!!
Numberofindividuals=varargin{1};
Maxgeneration=varargin{2};
IndependentNum=varargin{3};
SelectProbability=varargin{4};
RecombinationProbability=varargin{5};
Mutationprobability=varargin{6};
PrecisionofVariables=varargin{7};
vlb=varargin{8};
vub=varargin{9};
%%%%%%%%Numberofindividuals=50;%%染色体的数目.............举例设置参数值,这拥有九个自变量
%%%%%%%%Maxgeneration=500;%%%最大的迭代数目...........举例设置参数值
%%%%%%%%IndependentNum=5;%%自变量的个数............举例设置参数值
%%%%%%%%SelectProbability=0.9;%%选择概率..........举例设置参数值
%%%%%%%%RecombinationProbability=0.7;%%重组概率...........举例设置参数值
%%%%%%%%PrecisionofVariables=15;%%每个染色体到底有多长..........举例设置参数值
%%%%%%%%Mutationprobability=0.01; %%变异的概率..........举例设置参数值
%%%%%%%%vlb=[-5 -5 -5 -5 -5];vub=[5 5 5 5 5];函数自变量的上下界......举例参数设置
ObjFval=zeros(Maxgeneration,2);%%%%%%%%%用于遗传算法的性能跟踪
ub=[vlb;vub];%%%%%%%%建立自变量的区域控制
Field=[REP(PrecisionofVariables,[1,IndependentNum]);ub;...
    REP([1;0;1;1],[1,IndependentNum])];
%%%%%%%第一行:[len;                (num)
%%%%%%%第二行:lb;                (num)
%%%%%%%第三行:ub;                (num)
%%%%%%%第四行:code;                (0=binary     | 1=gray)
%%%%%%%第五行:scale;                (0=arithmetic | 1=logarithmic)
%%%%%%%第六行:lbin;                (0=excluded   | 1=included)
%%%%%%%第七行:ubin];                (0=excluded   | 1=included)
Chorome=CRTBP(Numberofindividuals,PrecisionofVariables*IndependentNum);%%%%染色体矩阵
P=BS2RV(Chorome,Field);
generation=0;
Fval=GEATexamplefun(P);
while generation<Maxgeneration
    f=RANKING(-Fval);%%%%%%%%%按照比例的大小分配适应度值
    FitFval=GEATfitfun(f,P);
    SelCh=SELECT('SUS',Chorome,FitFval,SelectProbability);
    SelCh=RECOMBIN('XOVSP',SelCh,RecombinationProbability);
    SelCh=MUT(SelCh,Mutationprobability);
    P=BS2RV(SelCh,Field);
    FvalSelect=GEATexamplefun(P);
    [Chorome,Fval]=REINS(Chorome,SelCh,1,1,Fval,FvalSelect);
    P=BS2RV(Chorome,Field);
    generation=generation+1;
    ObjFval(generation,1)=max(Fval);
    ObjFval(generation,2)=sum(Fval)/length(Fval);
end
[Bestfval,index]=max(Fval);
Independentvariables=P(index,:);
plot(ObjFval(:,1),'b--','linewidth',2)
hold on
plot(ObjFval(:,1),'r*','markersize',10)
plot(ObjFval(:,2),'g--','linewidth',2)
plot(ObjFval(:,2),'r*','markersize',10)
legend('解的变化','均值的变化');
end
    
    
    function s=GEATexamplefun(x)
    IndependentNum=size(x,2);
        zc=zeros(length(x),1);
        for i=1:length(x)
 ss=-2*pi+2*pi*exp(-0.2*sqrt(sum(x(i,:).^2)/IndependentNum))+exp(1/IndependentNum*sum(cos(2*pi*x(i,:))));
            zc(i)=ss;
        end
        s=zc;
    end
    function z=GEATfitfun(x,y)
        %%%%%%%x是函数值,y是种群的十进制值
        N=length(x);
        for i=1:length(N)
            if abs(sum(y(i,:)-500))>5%%%%%按照y的每一行测度自变量的总和是不是大于500,如果大于500则x(i)=0.001*x(i);
                x(i)=0.001*x(i);
            end
        end
        z=x;
    end
主程序in Command Windows:
 Numberofindividuals=50;%%染色体的数目
Maxgeneration=500;%%%最大的迭代数目
IndependentNum=2;%%自变量的个数
SelectProbability=0.9;%%选择概率
RecombinationProbability=0.7;%%重组概率
PrecisionofVariables=10;%%每个染色体到底有多长
Mutationprobability=0.01; 
vlb=[-2 -2];vub=[2 2];
[Bestfval,Independentvariables]=GEATsolvefun(Numberofindividuals,Maxgeneration,IndependentNum,...
SelectProbability,RecombinationProbability,Mutationprobability,PrecisionofVariables,...
vlb,vub)
或者:
 Numberofindividuals=50;%%染色体的数目
Maxgeneration=500;%%%最大的迭代数目
IndependentNum=5;%%自变量的个数
SelectProbability=0.9;%%选择概率
RecombinationProbability=0.8;%%重组概率
PrecisionofVariables=15;%%每个染色体到底有多长
Mutationprobability=0.02; 
vlb=[-3 -3 -3 -3 -3];vub=[3 3 3 3 3];
[Bestfval,Independentvariables]=GEATsolvefun(Numberofindividuals,Maxgeneration,IndependentNum,...
SelectProbability,RecombinationProbability,Mutationprobability,PrecisionofVariables,...
vlb,vub)
 扫码加好友,拉您进群
扫码加好友,拉您进群 
    
 
    

 收藏
收藏



















