声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 1468|回复: 7

[编程技巧] 能不能不用循环?

[复制链接]
发表于 2010-5-23 03:05 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
L=[2,4,5];
B= [1:10;1:10;1:10];

B是一个3*10的矩阵,想要结果是求出第一行从第一个到第二个的和,第二行从第一个到第四个的和,第三行从第一个到第五个的和。即:sum(B(1,1:2)), sum(B(1,1:4)), sum(B(1,1:5))
能不能不用循环。谢谢
回复
分享到:

使用道具 举报

发表于 2010-5-23 08:26 | 显示全部楼层
sum(B(1,1:2)), sum(B(1,1:4)), sum(B(1,1:5))
就可以
 楼主| 发表于 2010-5-23 21:36 | 显示全部楼层

回复 沙发 yufeng 的帖子

不好意思,没有说清楚。
比如B是10000000*10的矩阵,L是1*10000000,并且L中的数字是不一样的。目的是求出B中每一行的第一个到第L(i)的和。我现在的办法是用循环,很慢。有没有办法不用循环。

谢谢回复
发表于 2010-5-23 22:36 | 显示全部楼层

回复 板凳 re-us 的帖子

早找过! 一时没找着现成的函数! :@L
同待高人路过
可否请教L或B是否存在某些规律!?

[ 本帖最后由 ChaChing 于 2010-5-23 22:38 编辑 ]
发表于 2010-5-24 00:20 | 显示全部楼层

刚注意到一点, 若LZ以for ii=1:10000000循环, 当然很慢!
因L的范围一定是1~10, 何不试试以for ii=1:10循环!?
  1. aa=zeros(size(B,1),1);
  2. for ii=1:10, ind=find(L==ii);
  3.   if ~isempty(ind), aa(ind)=sum(B(ind,1:ii)'); end
  4. end
复制代码

本想用编辑, 怕LZ不知有回应! 等LZ试过再合并!
发表于 2010-5-24 00:40 | 显示全部楼层
循环速度慢的原因,就是频繁调用sum函数引起的,MATLAB高版本下,循环已经不是瓶颈了,往往函数调用的开销不能忽略。我在新书里对类似这样的情况进行了讨论,改进思路之一就是变“勤拿少取”为“少拿多取”,可以参考下面这个帖子:http://forum.vibunion.com/forum/thread-83299-1-36.html
至于楼主你的问题,我觉得可以这样来实现“少拿多取”:(Chaching兄的思路也很好,也是避免“勤拿少取”的一种方法,下面也附上代码)

  1. >> clear
  2. ind = repmat(1:10,10^6,1);
  3. L = unidrnd(10,10^6,1);
  4. loc = bsxfun(@le,ind,L);
  5. A = rand(10^6,10);
  6. tic;C = sum((A.*loc),2);toc
  7. E = zeros(10^6,1);
  8. tic;for k = 1:10^6,E(k) = sum(A(k,1:L(k)));end;toc
  9. isequal(C,E)
  10. Elapsed time is 0.277833 seconds.
  11. Elapsed time is 2.613414 seconds.
  12. ans =
  13.      1
  14. %按Chaching兄的思路
  15. %
  16. >> D = zeros(1e6,1);
  17. tic;
  18. for k = 1:10
  19. D(L==k) = sum(A(L==k,1:k),2);
  20. end
  21. toc;
  22. Elapsed time is 0.399268 seconds.
  23. >> isequal(C,D)
  24. ans =
  25.      1
复制代码

[ 本帖最后由 rocwoods 于 2010-5-24 00:50 编辑 ]

评分

1

查看全部评分

 楼主| 发表于 2010-5-24 04:15 | 显示全部楼层
两位的想法太牛了。
rocwoods的方法成功避免了for循环,受益匪浅呀。chacheng的想法很新颖,很好很好。
把rocwoods的C = sum((A.*loc),2);toc这个改成C = sum((ind.*loc),2), 就是我所要的结果了。
另外,chacheng的aa(ind)=sum(B(ind,1:ii)')改成aa(ind)=sum(B(ind,1:ii)',1),不然当ii是1的时候得不到想要的结果。比如:

clc; clear
tic
B = repmat(1:10,10^2,1);
L = [ones(50,1).*1,ones(50,1).*2];
aa=zeros(size(B,1),1);
for ii=1:2
    ind=find(L==ii);
   if ~isempty(ind), aa(ind)=sum(B(ind,1:ii)'); end
end
toc

谢谢,谢谢。

[ 本帖最后由 ChaChing 于 2010-5-24 11:25 编辑 ]
发表于 2010-5-24 11:24 | 显示全部楼层

回复 6楼 rocwoods 的帖子

高手就是高手! 底子强果然是有差的, 自叹不如!
由于目前是使用旧本(v5.6), roc所用的函数并没有, 尚无法验证学习, 回家再试!
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-9-21 20:36 , Processed in 0.065237 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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