以下是测试目前讨论的各种方法的基准。我正在使用 File Exchange 上的TIMEIT功能。
function [t,v] = testClampColumns()
% data and limits ranges for each column
r = 10000; c = 500;
M = randn(r,c);
mn = -1.1 * ones(1,c);
mx = +1.1 * ones(1,c);
% functions
f = { ...
@() clamp1(M,mn,mx) ;
@() clamp2(M,mn,mx) ;
@() clamp3(M,mn,mx) ;
@() clamp4(M,mn,mx) ;
@() clamp5(M,mn,mx) ;
};
% timeit and check results
t = cellfun(@timeit, f, 'UniformOutput',true);
v = cellfun(@feval, f, 'UniformOutput',false);
assert(isequal(v{:}))
end
给定以下实现:
1)循环所有值并与最小值/最大值进行比较
function M = clamp1(M, mn, mx)
for j=1:size(M,2)
for i=1:size(M,1)
if M(i,j) > mx(j)
M(i,j) = mx(j);
elseif M(i,j) < mn(j)
M(i,j) = mn(j);
end
end
end
end
2)将每列与最小值/最大值进行比较
function M = clamp2(M, mn, mx)
for j=1:size(M,2)
M(M(:,j) < mn(j), j) = mn(j);
M(M(:,j) > mx(j), j) = mx(j);
end
end
3)将每列截断到限制
function M = clamp3(M, mn, mx)
for j=1:size(M,2)
M(:,j) = min(max(M(:,j), mn(j)), mx(j));
end
end
4) (3) 中截断的向量化版本
function M = clamp4(M, mn, mx)
M = bsxfun(@min, bsxfun(@max, M, mn), mx);
end
5)绝对值比较:-a < x < a <==> |x| <一个
(注意:这不适用于您的情况,因为它需要一个对称的限制范围。我只是为了完整性而将其包括在内。此外,它原来是最慢的方法。)
function M = clamp5(M, mn, mx)
assert(isequal(-mn,mx), 'Only works when -mn==mx')
idx = bsxfun(@gt, abs(M), mx);
v = bsxfun(@times, sign(M), mx);
M(idx) = v(idx);
end
我在机器上使用大小为 10000x500 的输入矩阵的时间:
>> t = testClampColumns
t =
0.2424
0.1267
0.0569
0.0409
0.2868
我会说所有上述方法都足够快,bsxfun
解决方案是最快的:)