将整数转换为通用基础Matlab [英] Convert Integer to Generic Base Matlab
问题描述
我正在尝试将以10为底的整数k转换为以q为底的整数,但不是以标准方式.首先,我希望我的结果是向量(或字符串'a,b,c,...',以便可以将其转换为向量,而不是'abc ...').最重要的是,我希望每个数字"都以10为底.例如,假设我的数字为23(以10为基数),并且我想将其转换为12.在标准1,...,9,A,B表示法中为1B;但是,我希望它以[1,11]的形式出现.我只对0 \ le k \ le n ^ q-1的数字k感兴趣,其中n是预先固定的.
I'm trying to convert a base-10 integer k into a base-q integer, but not in the standard way. Firstly, I'd like my result to be a vectors (or a string 'a,b,c,...' so that it can be converted to a vector, but not 'abc...'). Most importantly, I'd like each 'digit' to be in base-10. As an example, suppose I have the number 23 (in base-10) and I want to convert it to base-12. This would be 1B in the standard 1,...,9,A,B notation; however, I want it to come out as [1, 11]. I'm only interested in numbers k with 0 \le k \le n^q - 1, where n is fixed in advance.
换一种说法,我希望找到系数a(r)使得
k = \sum_{r=0}^{n-1} a(r) q^r
其中每个a(r)以10为底. (请注意,0 \ le a(r)\ le q-1.)
Put another way, I wish to find coefficients a(r) such that
k = \sum_{r=0}^{n-1} a(r) q^r
where each a(r) is in base-10. (Note that 0 \le a(r) \le q-1.)
我知道我可以使用for循环来完成此操作-现在正努力获取确切的公式! -但我想将其向量化或使用快速的内部函数.
I know I could do this with a for-loop -- struggling to get the exact formula at the moment! -- but I want to do it vectorised, or with a fast internal function.
但是,我希望能够将n变大,因此宁愿选择比这更快的方法. (当然,我可以将其更改为parfor-loop或在GPU上执行;对于我当前的情况而言,这是不切实际的,因此,我希望使用更直接的版本.)
However, I want to be able to take n to be large, so would prefer a faster way than this. (Of course, I could change this to a parfor-loop or do it on the GPU; these aren't practical for my current situation, so I'd prefer a more direct version.)
我看过诸如dec2base,num2str,str2num,base2dec之类的东西,但是运气不好.任何建议将不胜感激.
I've looked at stuff like dec2base, num2str, str2num, base2dec and so on, but with no luck. Any suggestion would be most appreciated.
关于速度和空间,对于[0,q-1]或类似范围内的整数进行任何预分配也是不错的选择.
Regarding speed and space, any preallocation for integers in the range [0, q-1] or similar would also be good.
为清楚起见,我正在寻找一种适用于任何q和n的算法,可以转换[0,q ^ n-1]范围内的任何数字.
To be clear, I am looking for an algorithm that works for any q and n, converting any number in the range [0,q^n - 1].
推荐答案
You can use dec2base
and replace the characters by numbers:
x = 23;
b = 12;
[~, result] = ismember(dec2base(x,b), ['0':'9' 'A':'Z']);
result = result -1;
给予
>> result
result =
1 11
For any base (possibly above 36) you need to do the conversion manually. I once wrote a base2base
function to do that (it's essentially long division). The number should be input as a vector of digits in the origin base, so you need dec2base(...,10)
first. For example:
x = 125;
b = 6;
result = base2base(dec2base(x,10), '0':'9', b); % origin nunber, origin base, target base
给予
result =
3 2 5
或者如果您需要指定位数:
Or if you need to specify the number of digits:
x = 125;
b = 6;
d = 5;
result = base2base(dec2base(x,10), '0':'9', b, d)
result =
0 0 3 2 5
EDIT(2017年8月15日):纠正了两个错误:处理包含所有零"的输入(感谢 @Sanchises (注意),并在需要时用零"对输出进行正确的左填充.
EDIT (August 15, 2017): Corrected two bugs: handling of input consisting of all "zeros" (thanks to @Sanchises for noticing), and properly left-padding the output with "zeros" if needed.
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);
这篇关于将整数转换为通用基础Matlab的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!