将C样式代码转换为Matlab

时间:2013-08-13 17:10:09

标签: matlab vectorization matrix-indexing

我在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之类的东西让我出现内存错误。

3 个答案:

答案 0 :(得分: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)时,你选择了行(1,5,4)和这些行的每一个的列(3,4,5)!

>> 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;

答案 1 :(得分:1)

假设您有以下矩阵:

a = zeros(256);  % or initialized with other values
b = randi(256, [512 256]);
c = randi(256, [512 256]);

这是一个更快的矢量化解决方案:

a = a + sparse(b,c,1,size(a,1),size(a,2));

这是另一个:

a = a + accumarray([b(:) c(:)], 1, size(a));

答案 2 :(得分:-1)

答案:是的。

a(b, c) = a(b, c) + 1;

示例:

>> a = zeros(5);
>> b = [1,3];
>> c = [2,4,5];
>> a(b,c) = a(b,c) + 1;
>> a

a =

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