26

重複の可能性:
行列の各行を固定行で割るにはどうすればよいですか?

行列の各行から同じベクトルを減算するエレガントな方法を探しています。これは非エレガントな方法です。

a = [1 2 3];
b = rand(7,3);
c(:,1) = b(:,1) - a(1);
c(:,2) = b(:,2) - a(2);
c(:,3) = b(:,3) - a(3);

また、エレガントな方法は、この方法より遅くなることはありません。

私はもう試した

c = b-repmat(a,size(b,1),1); 

そしてそれは遅いようです。

編集:勝者はこの方法です。

c(:,1) = b(:,1) - a(1);
c(:,2) = b(:,2) - a(2);
c(:,3) = b(:,3) - a(3);

EDIT:より多くの方法、およびtic tocの結果:

n = 1e6;
m = 3;
iter = 100;
a = rand(1,m);
b = rand(n,m);

tic
c = zeros(size(b));
for i = 1:iter
    c(:,1) = b(:,1) - a(1);
    c(:,2) = b(:,2) - a(2);
    c(:,3) = b(:,3) - a(3);
end
toc

tic
c = zeros(size(b));
for i = 1:iter
    c(:,1) = b(:,1) - a(1);
    c(:,2) = b(:,2) - a(2);
    c(:,3) = b(:,3) - a(3);
end
toc

tic
c = zeros(size(b));
for i = 1:iter
    for j = 1:3
        c(:,j) = b(:,j) - a(j);
    end
end
toc

tic
for i = 1:iter
    c = b-repmat(a,size(b,1),1);
end
toc

tic
for i = 1:iter
    c = bsxfun(@minus,b,a);
end
toc

tic
c = zeros(size(b));
for i = 1:iter
    for j = 1:size(b,1)
        c(j,:) = b(j,:) - a;
    end
end
toc

結果

Elapsed time is 0.622730 seconds.
Elapsed time is 0.627321 seconds.
Elapsed time is 0.713384 seconds.
Elapsed time is 2.621642 seconds.
Elapsed time is 1.323490 seconds.
Elapsed time is 17.269901 seconds.
4

2 に答える 2

6

これが私の貢献です:

c = b - ones(size(b))*diag(a)

今それをスピードテストします:

tic
for i = 1:10000
    c = zeros(size(b));
    b = rand(7,3);
    c = b - ones(size(b))*diag(a);
end
toc

結果:

Elapsed time is 0.099979 seconds.

それほど速くはありませんが、きれいです。

于 2011-03-17T19:52:30.400 に答える
1

明らかな答えは 3 つしかありませんが、質問で 2 つ挙げました。

3 番目は行単位で、

c(1,:) = b(1,:) - a; %...

しかし、メモリの順序から要素にアクセスするため、大きな行列の列ごとの処理よりも遅くなると思います。

列ごとの処理を *.m ファイルまたはサブ関数のループに変えた場合でも、バージョンforよりも高速ですか?repmat

速度をテストするもう 1 つのこと: preallocating を試してくださいc

c = zeros(size(b));
c(:,1) = b(:,1) - a(1); %...
于 2011-03-17T17:43:26.467 に答える