找回密码
 注册
Simdroid-非首页
查看: 262|回复: 3

向量化编程:arrayfun函数的使用

[复制链接]
发表于 2007-8-13 11:08:42 | 显示全部楼层 |阅读模式 来自 北京海淀
我们知道,MATLAB编程核心思想之一就是向量化。MATLAB的很多built-in函数,向sin,cos,find等等都支持向量运算。但是,很多时候我们编写的函数的输入变量是标量,而我们又要对很多组参数进行函数调用,MATLAB7以前的版本中我们只能通过循环来实现,如果参数的维数增加,就会出现循环套循环的现象,效率恐怖。从MATLAB7.1开始,MATLAB新增arrayfun这个built-in函数来实现将任意函数应用到数组内包括结构在内的所有元素。这样很多以前不可避免的循环现在可以向量化了。举例如下:
      例1:生成一个这样的n*n矩阵a:a(i,j)=dblquad(@(u,v) sin(u)*sqrt(v),0,i,0,j)。以n=10为例,
      以前我们可能这样做:
  1. a=zeros(10);
  2. for ii=1:10
  3.   for jj=1:10
  4.      a(ii,jj)=dblquad(@(u,v) sin(u)*sqrt(v),0,ii,0,jj);
  5. end
  6. end
复制代码
现在我们只需这样:
  1. [J,I]=meshgrid(1:10);
  2. a1=arrayfun(@(ii,jj) dblquad(@(u,v) sin(u)*sqrt(v),0,ii,0,jj),I,J);
复制代码
例2:验证角谷猜想,一个正整数n,如果是偶数除以2,如果是奇数乘以3加1,得到的新数继续按上述规则运算,最后结果都为1。验证1到100000内的正整数。
先编写单个数的验证函数
  1. function f=jiaogu(n)
  2. while(n>1)
  3. if (mod(n,2)==1)
  4.     n=n*3+1;
  5. elseif(mod(n,2)==0)
  6.     n=n/2;
  7. else break;
  8. end
  9. end
  10. f=n;
复制代码
验证1:100000, 以前我们可能这样做:
  1. a=zeros(1,100000);
  2. for k=1:100000
  3. a(k)=jiaogu(k);
  4. end
  5. all(a)
复制代码
现在我们只需这样:
  1. all(arrayfun(@jiaogu,1:100000))
复制代码

举这两个例子目的是为了让大家知道很多以前不能优化的程序利用这个函数还可以进一步优化。具体了解请doc arrayfun 。另外cellfun和structfun也提供了类似的功能,关于其用法,帮助文档里写的很详细。

[ 本帖最后由 rocwoods 于 2007-8-13 11:28 编辑 ]

评分

1

查看全部评分

发表于 2007-8-13 11:17:23 | 显示全部楼层 来自 新疆乌鲁木齐
Simdroid开发平台
Excellent!
  1. [J,I]=meshgrid(1:10);
  2. a1=arrayfun(@(ii,jj) dblquad(@(u,v) sin(u)*sqrt(v),0,ii,0,jj),I,J);
复制代码

这个函数的用法相当好,可以深入探讨一下。不知道效率方面会怎么样,写有限元单刚积分时曾经用原始方法循环过,非常耗时间,rocwoods提供的这种新方式估计能改进很多。
回复 不支持

使用道具 举报

发表于 2007-8-13 12:02:39 | 显示全部楼层 来自 美国
赞。在文档中看到了一系列的函数,spfun之类的。且不说效率高低,至少会极高的提高程序的可读性。
回复 不支持

使用道具 举报

 楼主| 发表于 2007-8-13 12:12:36 | 显示全部楼层 来自 北京海淀
确实比较简洁。仔细想想发现这个函数的用处还真广泛。譬如
http://www.simwe.com/forum/thread-791320-1-1.html
5#楼问题可以这样做:
  1. data=rand(2800,24);
  2. Dat1=data(mod(1:2800,29)==0 | mod(1:2800,29)>=23,:);

  3. cellfun(@mean,arrayfun(@(k) Dat1(7*k-6:k*7,:),1:round(672/7),'UniformOutput',false),'UniformOutput' ,false)
复制代码
当然,还可以这样:
  1. cellfun(@mean,mat2cell(Dat1,7*ones(1,672/7),24),'UniformOutput',false);
复制代码

[ 本帖最后由 rocwoods 于 2007-8-13 15:09 编辑 ]
回复 不支持

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Simapps系列直播

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-10-7 05:19 , Processed in 0.048984 second(s), 18 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表