我想实现代码,它将通过二进制表示法添加两个整数。
例如:
a = [1 1 1 0];
和
b = [1 0 1 1];
所以我实现了以下算法:
function s=add_binary(a,b)
m=length(a);
s=zeros(m+1,0);
n=length(a);
c=0;
for ii=n:-1:1
d=floor((a(ii)+b(ii)+c)/2);
s(ii)=a(ii)+b(ii)+c-2*d;
c=d;
end
s(1)=c;
end
但是,它会返回结果:
s=add_binary(a,b)
s =
1 0 0 1
此处左侧应该有一个额外的1
,以便显示:
1 1 0 0 1
我在哪里犯了错误?
答案 0 :(得分:2)
这是我的解决方案
function s=add_binary(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=s';
end
>> s=add_binary(a,b)
s =
1 1 0 0 1
答案 1 :(得分:2)
2011年MATLAB Answers的问题讨论了这个问题。我想再提两个解决方案:
如果您有通讯系统工具箱,则可以使用bi2de
和de2bi
:
de2bi(bi2de(a,'left-msb') + bi2de(b,'left-msb'),'left-msb')
如果"数字"在输入中已知(且合理),一种解决方案可以是在一些数据结构中存储所有可能的输入组合,这将有助于快速访问。一个这样的例子是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
方法的优势将是显而易见的。
答案 2 :(得分:2)
由于您正在处理二进制数,为什么不使用logical operators?
function s = add_binary(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
测试:
>> a = randi([0 1], [1 6])
a =
0 1 0 1 0 1
>> b = randi([0 1], [1 6])
b =
1 1 0 0 0 1
>> s = add_binary(a, b)
s =
1 0 0 0 1 1 0
答案 3 :(得分:1)
使用num2str
将a
和b
转换为字符串,然后使用bin2dec
将其转换为小数。然后添加它们并使用dec2bin
将总和转换回二进制。使用num2cell
拆分字符串,最后使用str2double
获得所需的结果。
s=str2double(num2cell(dec2bin(bin2dec(num2str(a))+bin2dec(num2str(b)))))
% Output for given a and b
%---------------------------
% s =
% 1 1 0 0 1