在Matlab中更高效地遍历矩阵元素

3
我正在编写一些matlab代码,已经编写了一个算法,但我认为它不是特别高效。由于我想提高我的编程技能,我想知道是否有更有效的方法来实现这个算法。
我有一个(相当大的~ E07)值矩阵,这些值是无序的,但在范围[-100, 100]内。我想创建一个基于第一个矩阵的第二个矩阵,使用以下规则:
1. 如果点的值>70,则点的值应设置为70。 2. 如果点的值<-70,则点的值应设置为-70。 3. 所有其他值应四舍五入到最接近的5的倍数。
这是我目前正在做的事情:
data = 100*(-1+2*rand(1,10000000)); % create random dataset for stackoverflow
new_data = zeros(1,length(data));

for i = 1:length(data)
    if (data(i) > 70)
        new_data(i) = 70;
    elseif (data(i) < -70)
        new_data(i) = -70;
    else
        new_data(i) = round(data(i)/5.0)*5.0;
    end
end

是否有更高效的方法?我认为应该有一种使用逻辑索引的方法,但这对我来说是一个新的发现...

3个回答

8
您根本不需要使用循环:
data = 100*(-1+2*rand(1,10000000)); % create random dataset for stackoverflow
new_data = zeros(1,length(data)); % note that this memory allocation is not necessary at this point

new_data = round(data/5.0)*5.0;
new_data(data>70) = 70;    
new_data(data<-70) = -70;

这正是我想要的东西!谢谢 :) - FakeDIY

5

更简单的方法是使用max和min。只需一行代码即可完成。

new_data = round(5*max(-70,min(70,data)))/5;

不错。我更喜欢@H.Muster答案的可读性,但我认为这个一行代码更具计算效率。谢谢。 - FakeDIY

2

H.Muster和woodchips提供的两种答案当然是解决问题的方法,但仍有小的改进空间。如果你想追求性能,可能希望利用问题的特定性。例如,你的输出数据是整数-100 <= x <= 100。这显然适合于8位有符号整数数据类型。这段代码(注意从任意双精度数据的显式转换为int8

% your double precision input data
data = 100*(-1+2*rand(1,10000000));

% cast to int8 - matlab does usual round here
data = int8(data);
new_data = 5*(max(-70,min(70,data))/5);

之所以速度最快,有两个原因:

  • 1 数据元素只占用1个字节,而不是8个。这里的内存带宽是一个限制因素,所以你可以得到很大的改进
  • 不再需要round函数

下面是H.Muster、woodchips和我的小修改代码的一些时间记录:

H.Muster    Elapsed time is 0.235885 seconds.
woodchips   Elapsed time is 0.167659 seconds.
my code     Elapsed time is 0.023061 seconds.

差别非常明显。尽管MATLAB在任何地方都使用双精度,但在可能的情况下应尝试使用整数数据类型。

编辑 这是因为MATLAB实现整数算术的方式不同于C,将double转换为int时会隐含一个round操作:

a = 0.1;
int8(a)

ans =
  0

a = 0.9;
int8(a)

ans =
  1

有趣,谢谢。我实际上正在处理的数据不是整数集,而是全部都是双精度浮点数。 - FakeDIY
@FakeDIY,我显然没有表达清楚 :) 请使用与其他人相同的双重输入数据运行代码。它会给出相同的结果。您的输入数据不需要是整数 - 主要是您的输出数据是整数。我使用了一个明确的uint8转换,它进行了初始舍入并且是该方法的一部分。简而言之,对于您生成的测试数据,所有方法都产生相同的结果。 - angainor
啊,我明白了。数据类型不是我非常了解的东西——不过那确实是一个很好的方法。 :-) - FakeDIY

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接