2

私はCで次のコードを持っています:

for(i=0;i<m;i++)
{
    for(j=0;j<n;j++)
    {
        a[b[i]][c[j]]+=1;
    }
}

forループを使わずにMatlabでこれを書く方法はありますか? (:) を使用した Matlab の方法の方が高速です。

a(b(:),c(:))=a(b(:),c(:))+1メモリ不足エラーが発生するようなものです。

4

3 に答える 3

3

面白い。 私は(まだ)あなたのための解決策を持っていませんが(解決策は一番下にあります)、いくつかのメモとポインタがあります:

1. メモリ不足エラーは、右側に 512*256 x 512*256 要素の一時行列を作成しているためです ( a(b(:),c(:))+1)。つまり、2^34 バイト — 17GB です! そのため、メモリ不足エラーが発生しています。また、この配列はあなたが望むものでさえないことに注意してください! この例を見てください:

>> a = magic(5);
>> b = [1 5 4]; % The rows that contain the numbers 1,2,3 respectively
>> c = [3 4 5]; % The columns that contain ^ ...

今、a(1,3) == 1、a(5,4) == 2 などa(b,c)。それらの行のすべてに対して!

>> a(b,c)
ans =

     1     8    15
    25     2     9
    19    21     3

あなたが気にするのは対角線だけです。解決策は、sub2indを使用して添字ペアを線形インデックスに変換することです。

>> a(sub2ind(size(a),b,c))
ans =

     1     2     3

2. あなたが提案した解決策も、あなたが望んでいることにはなりません。Matlab にはインクリメント演算子がないため、(b,c) に存在するすべてのインデックスを 1 ずつインクリメントするだけです。そしてもうありません。これをベクトル化するには、創造的な思考が必要です。小さい配列を使用して、何が起こっているかを確認します。

>> a = zeros(4,4);
>> b = ones(8,4);
>> c = ones(8,4);
>> a(b,c) = a(b,c) + 1;
>> a
a =

     1     0     0     0
     0     0     0     0
     0     0     0     0
     0     0     0     0

編集どうぞ!ベクトル化されたインクリメント:

>> idxs = sub2ind(size(a),b(:),c(:)); % convert subscripts to linear indices
>> [unique_idxs,~,ic] = unique(idxs); % Get the unique indices and their locations
>> increment_counts = histc(ic,1:max(ic)); % Get the number of occurrences of each idx
>> a(unique_idxs) = a(unique_idxs) + increment_counts;
于 2013-08-13T17:50:26.623 に答える