如果输入中的“数字”数量是已知的(并且是合理的),一种解决方案可能是将所有可能的输入组合存储在某种数据结构中,这将有助于快速访问。一个这样的例子是MapN class(尽管它可以很容易地用常规数值数组来完成)。我将提供一个小例子来展示这个想法(包括基准):
function allResults = q43095156(allResults)
if nargin == 0
% Let's store all combinations of 8 binary digits:
in = uint8(0:255);
out = uint16(in)+uint16(in.');
outB = logical(de2bi(out(:),'left-msb'));
[in1,in2] = meshgrid(in,in);
allResults = MapN(...
num2cell([num2cell(in1(:),2),num2cell(in2(:),2)],2),...
num2cell(outB,2));
end
benchmark(allResults);
end
function benchmark(allResults)
rng(43095156);
a = logical(randi([0 1],10,8,'uint8'));
b = logical(randi([0 1],10,8,'uint8'));
% Test:
R{5} = de2bi(bi2de(a,'left-msb') + bi2de(b,'left-msb'),'left-msb');
R{4} = add_a_bunch_gnovice(a,b);
R{3} = add_a_bunch_Sardar(a,b);
R{2} = add_a_bunch_dato(a,b);
R{1} = getFromMap(a, b, allResults);
assert(isequal(R{:}));
% Benchmark:
a = logical(randi([0 1],1000,8,'uint8'));
b = logical(randi([0 1],1000,8,'uint8'));
fprintf(1,'\nSardar''s method:\t%f',timeit(@() add_a_bunch_Sardar(a, b) ));
fprintf(1,'\nDev-iL''s method:\t%f',timeit(@() getFromMap(a, b, allResults) ));
fprintf(1,'\ngnovice''s method:\t%f',timeit(@() add_a_bunch_gnovice(a, b) ));
fprintf(1,'\ndato''s method:\t\t%f',timeit(@() add_a_bunch_dato(a, b) ));
fprintf(1,'\nbi2de method:\t\t%f',timeit(@() de2bi(bi2de(a,'left-msb') + bi2de(b,'left-msb'),'left-msb')));
end
function out = getFromMap(a,b,map)
out = cell2mat(values(map, num2cell([ num2cell(bi2de(a,'left-msb'),2),...
num2cell(bi2de(b,'left-msb'),2)],2)));
end
function out = add_a_bunch_gnovice(a,b)
out = zeros(size(a)+[0,1],'logical');
for ind1 = 1:size(a,1)
out(ind1,:) = add_binary_gnovice(a(ind1,:), b(ind1,:));
end
end
function out = add_a_bunch_Sardar(a,b)
out = zeros(size(a)+[0,1],'logical');
for ind1 = 1:size(a,1)
out(ind1,:) = add_binary_Sardar(a(ind1,:), b(ind1,:));
end
end
function out = add_a_bunch_dato(a,b)
out = zeros(size(a)+[0,1],'logical');
for ind1 = 1:size(a,1)
out(ind1,:) = add_binary_dato(a(ind1,:), b(ind1,:));
end
end
function s = add_binary_gnovice(a, b)
a = [0 a];
b = [0 b];
c = a&b;
while any(c)
b = xor(a, b);
a = circshift(c, -1);
c = a&b;
end
s = a+b;
end
function s = add_binary_Sardar(a,b)
s = logical(str2double(num2cell(dec2bin(bin2dec(num2str(a)) +...
bin2dec(num2str(b)), numel(a)+1))));
end
function s = add_binary_dato(a,b)
m = length(a);
s = zeros(m+1,1);
n = length(a);
c = 0;
for ii = n:-1:1
d = floor((a(ii)+b(ii)+c)/2);
s(ii+1) = a(ii)+b(ii)+c-2*d;
c = d;
end
s(1) = c;
s = logical(s.');
end
我的 x64 MATLAB R2017a @ Win10 的结果是:
Sardar's method: 0.336414
Dev-iL's method: 0.061656
gnovice's method: 0.022031
dato's method: 0.002123
bi2de method: 0.000356
所以这应该让我们知道哪些方法更快(除非我把包装函数搞砸了)......
如果总和的计算是其他一些更昂贵的操作,MapN 方法的优势就会很明显。