algorithm - 将整数转换为通用基础 Matlab

标签 algorithm matlab decimal radix base-conversion

我正在尝试将以 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 是预先固定的。

换句话说,我希望找到系数 a(r) 使得 k =\sum_{r=0}^{n-1} a(r) q^r 其中每个 a(r) 的基数都是 10。 (注意 0\le a(r)\le q-1。)

我知道我可以用 for 循环来做到这一点——目前正在努力获得精确的公式! -- 但我想将其矢量化,或者使用快速的内部函数。

但是,我希望能够使 n 很大,所以更喜欢比这更快的方法。 (当然,我可以将其更改为 parfor 循环或在 GPU 上执行;这些对于我当前的情况来说并不实用,因此我更喜欢更直接的版本。)

我看过诸如 dec2base、num2str、str2num、base2dec 等内容,但没有运气。任何建议将不胜感激。

关于速度和空间,对范围 [0, q-1] 或类似范围内的整数进行任何预分配也很好。

需要明确的是,我正在寻找一种适用于任何 q 和 n 的算法,转换 [0,q^n - 1] 范围内的任何数字。

最佳答案

您可以使用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 日):更正了两个错误:处理由所有“零”组成的输入(感谢 @Sanchises 的注意),以及在需要时用“零”正确地向左填充输出.

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);

关于algorithm - 将整数转换为通用基础 Matlab,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40683265/

相关文章:

matlab - matlab中的梯度直方图

matlab - (将MATLAB脚本转换为Octave脚本)输出图中的LaTeX渲染

c - C中十进制到十六进制的转换

c# - 限制按键事件中小数点后的数字

python - 确定给定数组的任何排列是否使长度为 K 的所有子数组的总和相等

c - C中的RLE算法

matlab - 如何在 Matlab 中绘制二维 FFT?

python - 如何让 Python 处理 int 输入,将它们转换为两位小数?

linux - 用于调整/校准启发式算法属性的软件

php - 比 in_array 快?