将numpy数组转换为纯python整数以避免整数溢出

时间:2018-10-16 14:06:14

标签: python numpy

我之前曾问过这个问题,但被否决了。无论如何,根据没有人真的再次看到三重否决问题的事实来判断,我重新发布它以表明我对实际答案感兴趣(如果有的话)。

问题陈述:

在这种情况下,我需要纯python整数的任意精度功能。在我的代码中的某个时候,我有一个带有布尔值的numpy数组。像这样:

arr
  

array([True,False,False,False,True,True,True,False,True,           正确,错误,错误,正确,正确,正确,错误,正确,错误,          错误,正确,错误,正确,正确,正确,正确,正确,           正确,错误,正确,正确,错误,正确,正确,错误,正确,          错误,错误,正确,错误,正确,正确,错误,正确,错误,           正确,正确,错误,正确,正确,正确,错误,错误,错误,           正确,错误,错误,正确,正确,正确,正确,错误,正确,          False])

我使用numpy.int64将其转换为arr.astype(int)以使其算术。

但是我使用此代码将其转换为溢出的整数(并产生了我不想生成的负数)。

代码正在使用此函数(它是纯python,本身不会有任何整数溢出问题):

def bool2int(x):
    y = 0
    for i,j in enumerate(x):
        y += j<<i
    return y

如果我直接在np.array上运行代码(转换为int与否无关紧要):

bool2int(arr)
  

-2393826705255337647

bool2int(h.astype(int))
  

-2393826705255337647

我需要一个正整数。因此,我使用了列表理解:

bool2int([int(x) for x in arr])
  

16052917368454213969

很明显,arr表示的数字超出了固定精度整数(即2 63 -1)的容量,可以直接使用ti。

还有其他直接方法可以实现列表理解以外的功能吗?

编辑:

对于python中整数溢出的理论,我起诉了source

2 个答案:

答案 0 :(得分:2)

使用astype(int)似乎可以正常工作;以下代码:

import numpy as np

test = np.array([True, False, False, False, True, True, True, False, True, True, False, False, True, True, True, False, True, False, False, True, False, True, True, True, True, True, False, True, False, True, True, False, True, True, False, True, False, False, True, False, True, True, False, True, False, True, True, False, True, True, True, False, False, False, True, False, False, True, True, True, True, False, True, False])
test_int = test.astype(int)

print(test_int)
print(test_int.sum())

返回:

[1 0 0 0 1 1 1 0 1 1 0 0 1 1 1 0 1 0 0 1 0 1 1 1 1 1 0 1 0 1 1 0
1 1 0 1 0 0 1 0 1 1 0 1 0 1 1 0 1 1 1 0 0 0 1 0 0 1 1 1 1 0 1 0]

37

这里似乎不太可能出现溢出异常,因此我将再次调查该异常,因为也许其他地方有错误。

修改

如果要获取Python类型而不是numpy对象,请执行以下操作:

test.astype(int).tolist()

答案 1 :(得分:2)

获取本地Python类型元素的一种方法是.tolist()。请注意,我们可以直接在布尔数组上执行此操作。您的代码可以与本地Python bool正常工作。

>>> x = np.random.randint(0, 2, (100,)).astype(bool)
>>> x
array([ True,  True, False,  True, False,  True, False, False,  True,
       False, False,  True,  True, False, False, False,  True, False,
       False,  True, False,  True, False, False,  True,  True,  True,
        True,  True,  True,  True, False, False, False, False, False,
        True,  True,  True,  True, False, False,  True, False, False,
       False, False,  True, False,  True,  True, False, False,  True,
       False,  True,  True,  True, False,  True,  True,  True, False,
        True,  True,  True,  True, False,  True,  True,  True, False,
        True, False,  True, False,  True, False,  True,  True,  True,
       False, False,  True,  True,  True,  True,  True, False, False,
        True, False, False, False,  True,  True,  True, False, False,  True], dtype=bool)
>>> bool2int(x)
-4925102932063228254
>>> bool2int(x.tolist())
774014555155191751582008547627L

作为额外的奖励,它实际上更快。

>>> timeit(lambda:bool2int(x), number=1000)
0.24346303939819336
>>> timeit(lambda:bool2int(x.tolist()), number=1000)
0.010725975036621094