整数数组的基本转换

时间:2013-11-26 18:56:33

标签: python arrays math numpy

我正在尝试创建一个代码,将数组中的整数转换为给定的基础并填充它们以使它们具有相同的大小。我在Alex Martelli的stackoverflow代码中操作的以下代码在我应用numpy.vectorize时不起作用,尽管它适用于单个数组:

def int2base(x, base,size):
    ret=np.zeros(size)
    if x==0: return ret
    digits = []
    while x:
        digits.append(x % base)
        x /= base
    digits.reverse()
    ret[size-len(digits):]=digits[:]
    return ret
vec_int2base=np.vectorize(int2base)
vec_int2base(np.asarray([2,1,5]),base=3,size=3)

以下列错误终止:

...
   1640             if ufunc.nout == 1:
   1641                 _res = array(outputs,
-> 1642                              copy=False, subok=True, dtype=otypes[0])
   1643             else:
   1644                 _res = tuple([array(_x, copy=False, subok=True, dtype=_t)

ValueError: setting an array element with a sequence. 

有没有更好的方法为矢量案例编写它,我在这里缺少什么。

3 个答案:

答案 0 :(得分:2)

我使用" fromBase10"函数(下面)相当于我在汇编时编程的数量。请注意,它不会填充输出,但numpy.vectorize可以使用它。只是不要忘记填补。

## Execute this to convert a base 10 into any arbitrary base
def fromBase10(number, base):
    if not number:
        return '0'
    sign = 1 if number > 0 else -1
    alphanum = string.digits + string.ascii_lowercase
    nums = alphanum[:base]
    res = ''
    number *= sign

    while number:
        number, mod = divmod(number, base)
        res += nums[mod]
    return ('' if sign == 1 else '-') + res[::-1]

请注意,我在Stack Exchange上复制了其他人的基本例程,但我不再记得在哪里。我只是不想在我不认可的地方申请信贷:)

答案 1 :(得分:2)

这是一个矢量化的版本:

import numpy as np


def int2base(x, base, size=None, order='decreasing'):
    x = np.asarray(x)
    if size is None:
        size = int(np.ceil(np.log(np.max(x))/np.log(base)))
    if order == "decreasing":
        powers = base ** np.arange(size - 1, -1, -1)
    else:
        powers = base ** np.arange(size)
    digits = (x.reshape(x.shape + (1,)) // powers) % base
    return digits

如果x的形状为shp,则结果的形状为shp + (size,)。 如果未指定size,则尺寸基于x中的最大值。 order确定数字的顺序;使用order="decreasing"(默认值)将123转换为[1,2,3]。使用order="increasing"获取[3,2,1]。 (后者可能更自然,因为结果中数字的索引与该数字的基数相匹配。)

示例:

In [97]: int2base([255, 987654321], 10)
Out[97]: 
array([[0, 0, 0, 0, 0, 0, 2, 5, 5],
       [9, 8, 7, 6, 5, 4, 3, 2, 1]])

In [98]: int2base([255, 987654321], 10, size=12)
Out[98]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 5],
       [0, 0, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1]])

In [99]: int2base([255, 987654321], 10, order="increasing")
Out[99]: 
array([[5, 5, 2, 0, 0, 0, 0, 0, 0],
       [1, 2, 3, 4, 5, 6, 7, 8, 9]])

In [100]: int2base([255, 987654321], 16)
Out[100]: 
array([[ 0,  0,  0,  0,  0,  0, 15, 15],
       [ 3, 10, 13, 14,  6,  8, 11,  1]])

答案 2 :(得分:-1)

感谢 Warren 的这种矢量化实现。

我根据您的实现做了另一个更高效的矢量化实现。

def base_representation(x, base, size=None):
    x = np.asarray(x)
    if size is None:
        size = int(np.floor(np.log(np.max(x))/np.log(base)))+1
    arrays = []
    for _ in range(size):
        x, reminder = np.divmod(x, base)
        arrays.append(reminder)
    return np.stack(arrays, axis=-1)

请注意,尺寸上的错误已更正:公式应为 size=floor(log(x)/log(base))+1。

最好的问候。