2016-11-18 67 views
2

我试图将一个base-10整数k转换为base-q整数,但不是以标准方式。首先,我希望我的结果是一个向量(或一个字符串'a,b,c,...',以便它可以转换为向量,但不是'abc ...')。最重要的是,我希望每个“数字”以10为底。作为一个例子,假设我有23(基数为10),我想将它转换为base-12。在标准1,...,9,A,B表示法中这将是1B;但是,我希望它出来[1,11]。我只对数字k感兴趣,其中n是预先固定的。换句话说,我希望找到系数a(r),使得其中每个a(r)都是以10为底的系数。 (注意,0 \勒(R)\乐Q-1)。将整数转换为泛型基础Matlab

我知道我可以用一个for循环做到这一点 - 挣扎在此刻得到确切的配方! - 但我想要做矢量化,或者快速的内部功能。

不过,我希望能够把电量为大,所以宁愿比这更快的方式。 (当然,我可以将此更改为一个PARFOR环或做它的GPU。这些都不是我目前的情况实用,所以我更喜欢一个更直接的版本)

我已经看了像dec2base,num2str,str2num,base2dec等,但没有运气。任何建议将不胜感激。

关于速度和空间,任何预分配为在范围内的整数[0,Q-1]或类似的也将是很好的。

为了清楚起见,我寻找对于任何Q和n的工作的算法,变换范围内的任何数量的[0,Q^N - 1]。

+0

'floor',''''和'/'已经被向量化了。循环不是必需的。 – excaza

+0

啊,当然是!当然,我的for循环是垃圾,并没有提供我想要的所有= P - 让我改变它... –

回答

3

您可以用数字用dec2base并替换字符:

x = 23; 
b = 12; 
[~, result] = ismember(dec2base(x,b), ['0':'9' 'A':'Z']); 
result = result -1; 

>> result 
result = 
    1 11 

这适用于基地多达36只,由于dec2base限制。


对于任何碱基(可能高于36)需要手动进行转换。我曾经写过一个base2base函数来做到这一点(它本质上是长分区)。该数字应该作为原始数据的一个向量输入,因此您首先需要dec2base(...,10)。例如:

x = 125; 
b = 6; 
result = base2base(dec2base(x,10), '0':'9', b); % origin nunber, origin base, target base 

result = 
    3  2  5 

或者,如果你需要指定的位数:

x = 125; 
b = 6; 
d = 5; 
result = base2base(dec2base(x,10), '0':'9', b, d) 
result = 
    0  0  3  2  5 

编辑(2017年8月15日):更正2错误:处理包含所有“零”的输入(感谢@Sanchises注意),并正确地l如果需要,用“零”填充输出。

function Z = base2base(varargin) 
% Three inputs: origin array, origin base, target base 
% If a base is specified by a number, say b, the digits are [0,1,...,d-1]. 
% The base can also be directly an array with the digits 
% Fourth input, optional: how many digits the output should have as a 
% minimum (padding with leading zeros, i.e with the first digit) 
% Non-valid digits in origin array are discarded. 
% It works with cell arrays. In this case it gives a matrix in which each 
% row is padded with leading zeros if needed 
% If the base is specified as a number, digits are numbers, not 
% characters as in `dec2base` and `base2dec` 

if ~iscell(varargin{1}), varargin{1} = varargin(1); end 
if numel(varargin{2})>1, ax = varargin{2}; bx=numel(ax); else bx = varargin{2}; ax = 0:bx-1; end 
if numel(varargin{3})>1, az = varargin{3}; bz=numel(az); else bz = varargin{3}; az = 0:bz-1; end 
Z = cell(size(varargin{1})); 
for c = 1:numel(varargin{1}) 
    x = varargin{1}{c}; [valid, x] = ismember(x,ax); x = x(valid)-1; 
    if ~isempty(x) && ~any(x) % Non-empty input, all zeros 
     z = 0; 
    elseif ~isempty(x) % Non-empty input, at least a nonzero 
     z = NaN(1,ceil(numel(x)*log2(bx)/log2(bz))); done_outer = false; 
     n = 0; 
     while ~done_outer 
      n = n + 1; 
      x = [0 x(find(x,1):end)]; 
      y = NaN(size(x)); done_inner = false; 
      m = 0; 
      while ~done_inner 
       m = m + 1; 
       t = x(1)*bx+x(2); 
       r = mod(t, bz); q = (t-r)/bz; 
       y(m) = q; x = [r x(3:end)]; 
       done_inner = numel(x) < 2; 
      end 
      y = y(1:m); 
      z(n) = r; x = y; done_outer = ~any(x); 
     end 
     z = z(n:-1:1); 
    else % Empty input 
     z = []; % output will be empty (unless user has required left-padding) with the 
     % appropriate class 
    end 
    if numel(varargin)>=4 && numel(z)<varargin{4}, z = [zeros(1,varargin{4}-numel(z)) z]; end 
    % left-pad if required by user 
    Z{c} = z; 
end 
L = max(cellfun(@numel, Z)); 
Z = cellfun(@(x) [zeros(1, L-numel(x)) x], Z, 'uniformoutput', false); % left-pad so that 
% result will be a matrix 
Z = vertcat(Z{:}); 
Z = az(Z+1); 
+0

对不起,我正在寻找这样做的通用'Q',所以这不会不为我工作。我会在这个问题上更清楚一点。 –

+0

另外,用'x = 125'和'q = 16'(我假设你的意思只适用于'q',最多36; x可以是任何东西)给出结果[7,-1],当它应该是[7,13] ... –

+0

@SamT对不起,有一个错字。现在更正。对于36以上的基础,你需要手动完成(本质上是长分区)。我曾为此写过一个函数;让我找到它 –