【问题标题】:Addition of two integer in binary representation二进制表示中两个整数的加法
【发布时间】:2017-08-23 00:55:03
【问题描述】:

我想实现代码,通过二进制表示将两个整数相加。

例如:

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

我在哪里做错了?

【问题讨论】:

  • 不应该是s = zeros(m+1, 1)
  • 是的,我看到了,是错字,但还是有一些缺陷
  • str2double(num2cell(dec2bin(bin2dec(num2str(a))+bin2dec(num2str(b)))))
  • 我也解决了,我把它作为答案发布了
  • 任一输入可能具有的最大尺寸(位数)是多少?最大输出尺寸是多少?当我们在输出中需要比输入中更多的位时(如您的示例),我们应该总是添加另一个位,还是会在某个点“溢出”并保持相同的大小?

标签: matlab vector binary sum integer


【解决方案1】:

既然你在处理二进制数,为什么不使用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

【讨论】:

    【解决方案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
    

    【讨论】:

      【解决方案3】:

      2011 年在MATLAB Answers 上的一个问题中讨论了这个问题。我想再提两个解决方案:

      • 如果您有通信系统工具箱,您可以使用bi2dede2bi

        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 方法的优势就会很明显。

      【讨论】:

        【解决方案4】:

        使用num2strab 转换为字符串,并使用bin2dec 将它们转换为十进制。然后将它们相加并使用dec2bin 将总和转换回二进制。使用num2cell分割字符串,最后使用str2double得到想要的结果。

        s=str2double(num2cell(dec2bin(bin2dec(num2str(a))+bin2dec(num2‌​str(b)))))
        
        % Output for given a and b
        %---------------------------
        % s = 
        %   1     1     0     0     1
        

        【讨论】:

          猜你喜欢
          • 2019-08-04
          • 2015-01-21
          • 1970-01-01
          • 1970-01-01
          • 2021-02-13
          • 2019-02-04
          • 2018-03-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多