具有独立位/位数计算的 dec2base

问题描述

需要MATLAB/Octave dec2base 具有独立位/位数计算算法的功能函数(在整数逻辑中,没有除法,使用模算术)。

也很高兴:

  1. 匿名函数

注意! 标量只能使用一次浮点逻辑和除法来定义转换后的数字数组中的最大位数:

ceil( log2(max(dec(:)))/log2(base)) )

附言

  1. 针对简化的dec2bin 案例列出的解决方here
  2. 这篇博文中提供的 bitget解决方案:Matlab/Octave bitget function for any base

解决方法

  1. MATLAB / OCTAVE中:

    % For Matlab/Octave: 
    de2bs = @(dec,base) base.^([(1+floor( log2(max(dec(:)))/log2(base)) ):-1:1]-1); % an array of powers of a base
    de2bs = @(dec,base) sum(rem(dec(:)                                ...,base.*de2bs(dec,base)                 ...
                               )                                      ...
                            >=permute((1:base-1)'*(de2bs(dec,base))   ...,[3,2,1]                         ...
                                     )                                ...,3                                        ...
                            );          
    

    示例:

    x=0:9; base=3; de2bs(x,base)
    
    ans =
    
    0   0   0
    0   0   1
    0   0   2
    0   1   0
    0   1   1
    0   1   2           
    0   2   0
    0   2   1
    0   2   2
    1   0   0
    
  2. 仅在 OCTAVE 中:只要 Octave 支持匿名的默认值 函数,还有一个更有趣的重载函数 实施:

    % OCTAVE only (Matlab do not support default values for parameters)
    
    % Anonymous function de2bs
    % dig = digget(dec,base,isoutputasstring,pos)                
    %   dig  - returns the value of the digits in positions (pos) for numbers (dec)
    %          coverted to the defined base (for base=2 behaves similar to bitget) 
    %   dec  - mandatory,initial decimal numbers vector
    %   base - optional (by default base = 2),%          base to convert (for binary base = 2 )
    %   isoutputasstring - optional (by default isoutputasstring = true),%          example: de2bs(26,16,0) -> '1A'
    %          example: de2bs(26,1) -> [1 10]%   
    %   pos  - optional (by default pos = (ceil( log2(max(dec(:)))/log2(base)) ):-1:1 ) 
    %          array of positions (like in bitget function)
    
    de2bs = @(dec,base = [2]                                                  ... % Base of numbers you want to get,isoutputinstringformat = [true]                             ... % output format 0/1 - integer/string,pos  = [(ceil( log2(max(dec(:)))/log2(base)) ):-1:1]        ... % Bits/digits positions to return (similar to bitget function)
        ... % temporary variables listed below (NOT parameters)          ...,pbs  = [base.^(pos-1)]                                      ... % pbs - powers of base,num  = [sum(rem(dec(:)                                      ... % conversion to defined base,base.*pbs                                   ...
                            )                                            ...
                        >= permute((1:base-1)'*pbs                       ...,1]                               ...
                                  )                                      ...,3                                               ...
                        )                                                ...
                    ]                                                    ...
            )                                                            ...
            ifelse(isoutputinstringformat                                ... % Convert digits to chars if necessary,char(ifelse(num>9,num+55,num+48))                    ... % like 9->'9',10->'A',11->'B';,num                                                   ... 
                  );
    

    示例:

    x=25:28;
    base=16;
    
    
    de2bs(x)        % behaves as dec2bin(x)
    
    ans =
    
    11001
    11010
    11011
    11100        
    
    
    de2bs(x,base)   % behaves as dec2base(x,base)
    
    ans =
    
    19
    1A
    1B
    1C
    
    
    de2bs(x,0) % behaves as dec2base(x,base) without converting/mapping to string/char format
    
    ans =
    
    1    9
    1   10
    1   11
    1   12
    
    
    de2bs(x,1,[3 2 1])   % behaves as dec2base(x,base),but returns mentioned digits in number (like in bitget function)
    
    ans =
    
    019
    01A
    01B
    01C
    
,

如果您需要它作为常规函数(需要具有 Compatible Array Sizes for Basic Operations 支持的 MatLab 版本):

function dig = de2bs(dec,isoutputnumerical,pos) 
% de2bs(D)
% de2bs(D,BASE)
% de2bs(D,BASE,ISOUTPUTNUMERICAL)  
% de2bs(D,ISOUTPUTNUMERICAL,POS)
%
% de2bs(D)
%     Return a binary number corresponding to the non-negative integer D
%     (Behaves the same as dec2bin(D) )
%     
%         de2bs([123,321])  
%         ans = 001111011
%               101000001
%
% de2bs(D,BASE)
%     Return a string of symbols in base BASE corresponding 
%     to the non-negative integer D.
%     
%         de2bs(123,3)  
%         ans = 011120
%               102220
%  
%     If BASE is a string then the base is calculated as length(BASE),%     and characters of BASE are used as the symbols for the digits of D.  
%
%          de2bs (123,"aBc")
%          ans = aBBBca
%                Baccca
% 
% de2bs(D,ISOUTPUTNUMERICAL)  
%     By default,ISOUTPUTNUMERICAL is false   
%
%          de2bs([123,321],0) 
%          ans = 07B
%                141
%
%          de2bs([123,1) 
%          ans = 0    7   11
%                1    4    1
%
%
% de2bs(D,POS)
%     POS  - optional array of digits positions (like in bitget function)
%            By default pos = (ceil( log2(max(dec(:)))/log2(base)) ):-1:1 ) 
%
%          dde2bs([123,3,0)          
%          ans = 011120
%                102220
%           
%          de2bs([123,8:-2:2)
%          ans = 0012
%                0122
%
% See also: dec2base,base2dec,dec2bin,dec2hex.


% parsing input parameters ------------------------------------------
if nargin < 2  base = 2; end

symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

if (ischar(base))  symbols = base;  base = length(symbols); end
if  nargin < 3  isoutputnumerical = false; end

max_len = ceil( log2(max(dec(:)))/log2(base));

if  nargin < 4  pos = [max_len:-1:1]; end


% Conver decimals into base -----------------------------------------
pbs = [base.^(pos-1)];        % pbs - powers of base
dig = sum(rem(dec(:),base.*pbs) >= permute((1:base-1)'*pbs,1]),3);

if isoutputnumerical == false  dig = reshape(symbols(dig+1),size(dig)); end