numpy数组列出转换问题

时间:2013-11-05 14:24:04

标签: python arrays numpy

出于某种原因,evalRow(list(array([0, 1, 0, 0, 0])))evalRow([0, 1, 0, 0, 0])会给出不同的结果。但是,如果我使用magicConvert(此处调试此)而不是list从numpy数组转到列表,它将按预期工作。这是numpy中的一个错误吗?

def magicConvert(a):
  ss = str(list(a))[1:-1]
  return map(int, ss.split(","))

# You don't actually need to read these functions, just here to reproduce the error:
from itertools import *
def evalRow(r):
  grouped = map(
    lambda (v, l): (v, len(tuple(l))),
    groupby(chain([2], r, [2])))
  result = 0
  for player in (1, -1):
    for (pre, mid, post) in allTuples(grouped, 3):
      if mid[0] == player:
        result += player * streakScore(mid[1], (pre[0] == 0) + (post[0] == 0))
  return result

def streakScore(size, blanks):
  return 0 if blanks == 0 else (
    100 ** (size - 1) * (1 if blanks == 1 else 10))

def allTuples(l, size):
  return map(lambda i: l[i : i + size], xrange(len(l) - size + 1))

2 个答案:

答案 0 :(得分:10)

行为的差异是由于执行list(some_array)返回numpy.int64列表,同时通过字符串表示进行转换(或等效使用tolist()方法)返回python int的列表:

In [21]: import numpy as np

In [22]: ar = np.array([1,2,3])

In [23]: list(ar)
Out[23]: [1, 2, 3]

In [24]: type(list(ar)[0])
Out[24]: numpy.int64

In [25]: type(ar.tolist()[0])
Out[25]: builtins.int

我认为罪魁祸首是代码的100 ** (size - 1)部分:

In [26]: 100 ** (np.int64(50) - 1)
Out[26]: 0

In [27]: 100 ** (50 - 1)
Out[27]: 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

In [28]: type(100 ** (np.int64(50) - 1))
Out[28]: numpy.int64

你看到的是int64溢出,因此取幂的结果基本上是“随机的”,而python的int具有无限的范围并给出正确的结果。

总结:

  • 如果要在numpy和python数据类型之间进行转换,请使用正确的方法,在本例中为array.tolist()
  • 请记住,numpy的数据类型的范围有限,因此应检查溢出并在其他情况下预期会出现奇怪的结果。如果您没有使用正确的转换方法,那么当您没有预期时(例如,在这种情况下),最终可能会使用numpy数据类型。
  • 从不假设它是python / numpy /一个非常广泛使用的库中的错误。在这些经过充分测试和广泛使用的软件中找到这些琐碎案例中的错误的机会是非常小。如果程序给出了意想不到的结果,那么99.999%的时间是因为做错了什么。因此,在责备其他人之前,请尝试逐步检查您的计划正在做什么。

答案 1 :(得分:3)

我测试了它,它给了我不同的结果。不要问我为什么,也许是一个bug?

无论如何总是使用tolist()函数将numpy数组转换为列表。

evalRow(array([0, 1, 0, 0, 0]).tolist()) == evalRow([0, 1, 0, 0, 0])
#output: True