dec2base with independent bits/digits calculation
Asked Answered
V

2

0

Need MATLAB/Octave dec2base functionality function with independent bits/digits calculation algorithm (within integer logic, with no divisions, using modular arithmetic).

Would be nice to have as well:

  1. anonymous function

NB! floating logic and division could be used only one time for scalar to define the maximal amount of digits in converted numbers array:

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

The best answers:

  1. Anonymous function solution
  2. Regular Function solution

P.S.

  1. Solution for simplified dec2bin case listed here.
  2. Solution for bitget provided in this post: Matlab/Octave bitget function for any base
V1 answered 13/4, 2021 at 15:26 Comment(3)
How can “must be anonymous function” ever be a meaningful requirement?Damiondamita
@CrisLuengo, thank you for the remark. Question updated, impicit "must" replaced by explicit "nice to have"V1
@CrisLuengo, regarding "meaningful requirement": 1) In some scenarious anonymous functions work faster (in my tests for the small (around 100) input arrays for instance). 2) If you have anonymous function, not a big deal to write the regular function. Can't say the same for vice versa scenario. 3) I just sympathize to compact solutions (very personal). ;)V1
V
4
  1. In 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                                        ...
                            );          
    

    Example:

    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. In OCTAVE only: as far as Octave supports default values for anonymous functions, there is a more interesting overloaded function implementation:

    % 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,16,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                       ...
                                  ,[3,2,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                                                   ... 
                  );
    

    Examples:

    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,base,0) % behaves as dec2base(x,base) without converting/mapping to string/char format
    
    ans =
    
    1    9
    1   10
    1   11
    1   12
    
    
    de2bs(x,base,1,[3 2 1])   % behaves as dec2base(x,base), but returns mentioned digits in number (like in bitget function)
    
    ans =
    
    019
    01A
    01B
    01C
    
V1 answered 13/4, 2021 at 15:26 Comment(0)
V
0

If you need it as regular function (requires MatLab version with Compatible Array Sizes for Basic Operations support):

function dig = de2bs(dec, base, isoutputnumerical, pos) 
% de2bs(D)
% de2bs(D, BASE)
% de2bs(D, BASE, ISOUTPUTNUMERICAL)  
% de2bs(D, BASE, 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, BASE, ISOUTPUTNUMERICAL)  
%     By default, ISOUTPUTNUMERICAL is false   
%
%          de2bs([123,321],16,0) 
%          ans = 07B
%                141
%
%          de2bs([123,321],16,1) 
%          ans = 0    7   11
%                1    4    1
%
%
% de2bs(D, BASE, ISOUTPUTNUMERICAL, POS)
%     POS  - optional array of digits positions (like in bitget function)
%            By default pos = (ceil( log2(max(dec(:)))/log2(base)) ):-1:1 ) 
%
%          dde2bs([123,321],3,0)          
%          ans = 011120
%                102220
%           
%          de2bs([123,321],3,0,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,[3,2,1]),3);    % TODO - with for loop requires less calculations (this is just example with compact code)

if isoutputnumerical == false  dig = reshape(symbols(dig+1), size(dig)); end
V1 answered 16/7, 2021 at 10:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.