【发布时间】:2011-01-13 05:51:17
【问题描述】:
我有两个大约 1000 行和 1000 列的大数组。我需要比较这些数组的每个元素,如果对应的元素相等,则将 1 存储在另一个数组中。
我可以使用 for 循环来做到这一点,但这需要很长时间。我怎样才能更快地做到这一点?
【问题讨论】:
-
总是,尽可能对 MATLAB 代码进行矢量化。
标签: matlab comparison matrix vectorization
我有两个大约 1000 行和 1000 列的大数组。我需要比较这些数组的每个元素,如果对应的元素相等,则将 1 存储在另一个数组中。
我可以使用 for 循环来做到这一点,但这需要很长时间。我怎样才能更快地做到这一点?
【问题讨论】:
标签: matlab comparison matrix vectorization
如果您的两个矩阵 A 和 B 大小相同,那么您可以这样做:
index = A == B;
和index 将是一个logical array,其中A 和B 的元素处处相等,否则为零。
一句警告……
如果A 和B 包含整数,上面应该没问题。但是,如果它们包含浮点值,您可能会得到不希望的结果。对于 完全 相等的元素,上面的代码只会有值 1。即使是最小的差异也会导致元素被认为是不平等的。
您可以查看this question's answers,了解有关处理“浮点运算的危险”的更多信息。一种解决方案是检查数组元素是否在彼此的给定容差范围内,如下所示:
tolerance = 0.0001;
index = abs(A-B) <= tolerance;
上面将为您提供一个逻辑数组index,其中A 和B 的元素在0.0001 范围内,否则为零。
【讨论】:
只需使用普通的== 运算符:
>> [1 2; 3 4] == [1 5; 6 4]
ans =
1 0
0 1
【讨论】:
给出的答案都是正确的。我只是想详细说明gnovice's 关于浮点测试的评论。
在比较浮点数是否相等时,需要使用容差值。通常使用两种类型的公差比较:绝对公差和相对公差。 (source)
a 和 b 的绝对容差比较如下所示:
|a-b| < tol
相对容差比较如下:
|a-b| < tol*max(|a|,|b|) + tol_floor
您可以将以上两个实现为匿名函数:
%# absolute tolerance equality
isequalAbs = @(x,y,tol) ( abs(x-y) <= tol );
%# relative tolerance equality
isequalRel = @(x,y,tol) ( abs(x-y) <= ( tol*max(abs(x),abs(y)) + eps) );
然后您可以将它们用作:
%# let x and y be scalars/vectors/matrices of same size
x == y
isequalAbs(x, y, 1e-6)
isequalRel(x, y, 1e-6)
【讨论】:
isequal(0.3,0.1*3),相当于0.3 == 0.1*3。两者的答案都是错误的!
tol*eps(max(abs(x),abs(y))) 之类的东西,它应该为您提供在 x 和 y 的值范围内的浮点精度(乘以 tol)。跨度>
isequal 返回一个布尔值; OP 想要一个二元函数,它采用 2 个相同大小的矩阵并生成一个该大小的布尔矩阵。
tol_floor 值在 a 和 b 非常接近 0 时充当绝对容差。我只是选择使用eps。事实上,您可以根据需要省略它并将其定义为:abs(x-y) <= tol*max(abs(x),abs(y)),其中用户为tol 选择一个值(一个好的默认值是1e-8)