将整数转换为通用基础Matlab [英] Convert Integer to Generic Base Matlab

查看:149
本文介绍了将整数转换为通用基础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

由于对于任何基数(可能在36以上),您需要手动进行转换.我曾经写过一个base2base函数来做到这一点(本质上是长除法).该数字应在原点输入为数字向量,因此首先需要dec2base(...,10).例如:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆