5

出于某种原因,evalRow(list(array([0, 1, 0, 0, 0])))evalRow([0, 1, 0, 0, 0])给出不同的结果。但是,如果我使用magicConvert(在这里调试它)而不是list从 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))
4

2 回答 2

10

行为的不同是由于doinglist(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 的ints 具有无限范围并给出正确的结果。

总结一下:

  • 如果要在numpy和 python 数据类型之间进行转换,请使用正确的方法,在这种情况下array.tolist()
  • 请记住,numpys 数据类型的范围有限,因此应该检查溢出并在其他情况下期待奇怪的结果。如果您不使用正确的方法进行转换,您可能会numpy在未预料到的情况下使用数据类型(如本例所示)。
  • 永远不要认为这是 python/ numpy/ 一个非常广泛使用的库中的错误。在如此经过充分测试和广泛使用的软件中,在如此微不足道的情况下发现错误的机会非常小。如果程序给出了意想不到的结果,99.999% 的时间是因为做错了什么。因此,在责备他人之前,请尝试逐步检查您的程序在做什么。
于 2013-11-05T14:41:55.883 回答
3

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

无论如何,始终使用该tolist()函数将 numpy 数组转换为列表。

evalRow(array([0, 1, 0, 0, 0]).tolist()) == evalRow([0, 1, 0, 0, 0])
#output: True
于 2013-11-05T14:31:40.997 回答