【问题标题】:Command to pad zeros to specific locations in binary numbers?将零填充到二进制数中的特定位置的命令?
【发布时间】:2013-12-30 23:39:55
【问题描述】:

我需要将零填充到二进制数中的特定位置。循环二进制数的数组形式(例如dec2bin(43))并添加零并调整大小听起来轮子的重新发明。

如何在 Matlab 中有效地将零填充到二进制数?

循环

positions=[1,3,6];
x=de2bi(43);
xx=flip(x);    

kk=1;
for ii=1:length(x)+length(positions)
    if isequal(positions(kk),xx(ii))
         %Transfer the tail from ii by one index ahead,
         %left out here because I think my method is bad!
         x(ii)=0;
         positions=positions+1;  %Increase positions by one now due to one padding
         kk=kk+1;
    end
end

这感觉太重创了:基本上如何在 Y 之前得到 0,比如从 xxxxYabcd 到 xxxx0Yabcd,其中 xxxxYabcd 是二进制数?

示例

输入

101011, (1,3,6)

输出

100100110

1x010x11x(在插入零的位置用 x 显示更清晰的零位置)

【问题讨论】:

  • 如果您正在寻找效率,您可能需要一个可以一次填充所有数字的解决方案(而不是一个一个)。运行每个提供的解决方案 10000 次将需要几秒钟,而在 10000x5 矩阵上运行我的解决方案只需要几分之一秒。
  • 为什么要这样做?请为您的问题提供一些背景信息。
  • @starblue 更容易认为这是位移问题? Q 可以重新表述为从许多位置开始的位移概率,我觉得可能有一个优雅的位移解决方案来做到这一点。我还不知道这个问题是否存在一些特定的学术术语。我概述了位移的想法here,我还不确定如何优雅地做到这一点。填充零问题在处理数组时受到了太多关注,希望现在在位方面得到更多关注。

标签: matlab bit-manipulation


【解决方案1】:

虽然没有太大的概念改进,但以下将自动重新索引并在预填充矩阵上分配旧值:

>> xx
xx =
     1     0     1     0     1     1

nPads = length(positions);
nPadsShifts = 1:nPads;           
y = ones(1, length(xx) + nPads); % re-indexing on the new array
y(positions + nPadsShifts) = 0;  % padding values
y(y==1) = xx;                    % set original bit values


>> y
y =
     1     0     0     1     0     0     1     1     0

【讨论】:

    【解决方案2】:

    您可以仅使用索引来完成。要在扩展向量中插入的零的位置是 insertzeros+(1:length(insertzeros))(在您的示例中,insertzeros[1 3 6]):

    input = [1 0 1 0 1 1]; %// example data
    insertzeros = [1 3 6]; %// example data
    
    output = ones(1,length(input)+length(insertzeros));
    output(insertzeros+(1:length(insertzeros))) = 0;
    output(output==1) = input;
    

    【讨论】:

    • 迄今为止最快的方法,+1 表示最快——我还不知道为什么这是最快的。使用带有问题的小示例的热身代码进行测试。
    • @hhh 与 thewaywewalk 相比,它使用矩阵而不是元胞数组。与我的解决方案相比,它使用逻辑索引而不是下标索引。这个答案和 gevang 采取的步骤几乎相同,这就是为什么计算时间相似。
    【解决方案3】:

    比赛开始! Mendo 获胜,gevang 获得第二名,thewaywewalk 获得第三名,jaheruddin 获得第四名。 Shai 的bitshifting 是在 shai 函数中实现的,遗憾的是还没有让它运行得更快。

    结果

    gevang :2.2e-05
    thewaywewalk :5.6975e-05
    mendo :2.2102e-05
    jaheruddin :0.0001693
    shai (poor hhh-implementation) 5.3288e-04
    

    答案的热身测试

    function test_padding_zeros()
    
        function myOutput=gevang(xx,positions)
            nPads = length(positions);
            nPadsShifts = 1:nPads;
            myOutput = ones(1, length(xx) + nPads); % re-indexing on the new array
            myOutput(positions + nPadsShifts) = 0;  % padding values
            myOutput(myOutput==1) = xx;                    % set original bit values
        end
    
        function myOutput=thewaywewalk(x,positions)
            idx = numel(x):-1:1;
            myOutput = num2cell(x);
            myOutput(2,idx(positions)) = {0};
            myOutput = [myOutput{:}];
        end
    
        function myOutput=jaheruddin(myInput,positions) % myInput can be a row vector or a matrix!
            n = size(myInput,2)+numel(positions);
            myOutput = false(size(myInput,1),n);
            myOutput(:,setxor((1:length(positions)),1:n))=myInput;
        end
    
        function myOutput=mendo(myInput,positions)
            myOutput = ones(1,length(myInput)+length(positions));
            myOutput(positions+(1:length(positions))) = 0;
            myOutput(myOutput==1) = myInput;
        end
    
        function out = bizarreBitShift( bNum, fromBit, shiftAmount )
            % construct a mask
            msk = uint32( (2^( fromBit - 1 ) )-1 ); 
            shiftPart = bitand( uint32(bNum), bitcmp(msk) ); % bitcmp - complement of bits
            staticPart = bitand( uint32(bNum), msk );
            out = bitshift( shiftPart , shiftAmount );
            out = bitor( out, staticPart );
        end
    
        function myOutput=shai(myInput,positions)
            shiftAmount=1;
            myOutput=sprintf('%d',myInput);
            myOutput=bin2dec(myOutput);
            k=0;
            for ii=1:length(positions)
                fromBit=positions(ii)+k;
                myOutput=bizarreBitShift(myOutput, fromBit, shiftAmount);
                k=k+1;
            end
    
            myOutput=ismember(dec2bin(myOutput),'1');
        end
    
    
    
    
    positions = [1 3 6]; %// example data
    myInput = [1 0 1 0 1 1]; %// example data
    
    ggevang=@() gevang(myInput,positions);
    tthewaywewalk=@() thewaywewalk(myInput,positions);
    mmendo=@() mendo(myInput,positions);
    jjaheruddin=@() jaheruddin(myInput,positions);
    sshai=@() shai(myInput,positions);
    
    timeit(ggevang)
    timeit(tthewaywewalk)
    timeit(mmendo)
    timeit(jjaheruddin)
    timeit(sshai)
    
    end
    

    【讨论】:

    • 有趣的是,我使用了基于 tic/toc 的基准代码,而 gevang 的答案是 Luis Mendo 的两倍。但是对于每个函数的 10000 次运行。
    • 这也是我的答案可以计时的方式,注意它比较慢,但也可以接受矩阵。我的观点是,如果您想要速度,请考虑是否可以使用 10000x5 矩阵而不是 10000 个 1x5 向量来做到这一点。 --- 代码中的一些 cmets:我删除了全局声明,因为匿名函数自动可以访问父工作区,并且我还重命名了 input,因为这实际上是一个函数名。为了便于比较,我将所有输入和输出重命名为 myInputmyOutput
    【解决方案4】:

    如果您正在寻找效率,那么尝试各种选择永远不会有坏处。这是另一种方法:

    M = magic(5)>3; % Example matrix
    positions = [2 3 6]; % Desired padding columns in resulting matrix
    
    n = size(M,2)+numel(positions);
    R = false(size(M,1),n);
    
    R(:,setxor(positions,1:n))=M
    

    【讨论】:

    • 在进行基准测试时,您的解决方案似乎没有为 OP 的输入提供正确的结果。有没有考虑过OP从最后一位开始计算位置?
    • 对不起,但不幸的是我无法理解这是如何工作的,所以无法为您腾出时间,对不同的答案进行了一些热身测试here。如果您澄清您的答案,我会将您的方法也添加到比赛中,圣诞快乐! :)
    【解决方案5】:

    Shai 为单个二进制数提供了here 位移解决方案。我在下面使用它来填充零,该解决方案可能会变得更快——目前是最慢的解决方案之一(一些不必要的 dec2bin)或与 Jaheruddin 的解决方案大致相同的速度。

    function out = bizarreBitShift( bNum, fromBit, shiftAmount )
        % construct a mask
        msk = uint32( (2^( fromBit - 1 ) )-1 ); 
        shiftPart = bitand( uint32(bNum), bitcmp(msk) ); % bitcmp - complement of bits
        staticPart = bitand( uint32(bNum), msk );
        out = bitshift( shiftPart , shiftAmount );
        out = bitor( out, staticPart );
    end
    
    function myOutput=shai(myInput,positions)
        shiftAmount=1;
        myOutput=sprintf('%d',myInput);
        myOutput=bin2dec(myOutput);
        k=0;
        for ii=1:length(positions)
            fromBit=positions(ii)+k;
            myOutput=bizarreBitShift(myOutput, fromBit, shiftAmount);
            k=k+1;
        end
    
        myOutput=ismember(dec2bin(myOutput),'1');
    end
    
    positions = [1 3 6]; %// example data
    myInput = [1 0 1 0 1 1]; %// example data
    
    sshai=@() shai(myInput,positions);
    timeit(sshai)
    

    时机

    ans =
    
       5.3288e-04
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-18
      • 1970-01-01
      • 2011-12-02
      • 1970-01-01
      • 2017-03-22
      • 1970-01-01
      • 1970-01-01
      • 2020-03-20
      相关资源
      最近更新 更多