出于某种原因,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))
答案 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
数据类型。numpy
/一个非常广泛使用的库中的错误。在这些经过充分测试和广泛使用的软件中找到这些琐碎案例中的错误的机会是非常小。如果程序给出了意想不到的结果,那么99.999%的时间是因为你做错了什么。因此,在责备其他人之前,请尝试逐步检查您的计划正在做什么。答案 1 :(得分:3)
我测试了它,它给了我不同的结果。不要问我为什么,也许是一个bug?
无论如何总是使用tolist()
函数将numpy数组转换为列表。
evalRow(array([0, 1, 0, 0, 0]).tolist()) == evalRow([0, 1, 0, 0, 0])
#output: True