numpy.array如何选择默认数据类型?

vyu0f0g1  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(87)

当涉及2**64顺序的一些数字并且没有指定数据类型时,numpy.array()函数的行为似乎相当奇怪。有人能解释这种行为吗?这是一个bug,还是预期的?

$ python3
Python 3.10.8 (main, Nov 30 2022, 10:05:23) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.__version__
'1.23.5'
>>> np.array([2**63-1]).dtype
dtype('int64')
>>> np.array([2**64-1]).dtype
dtype('uint64')

到目前为止,我认为它是有意义的,int64可能是默认值,但它不能表示2**64-1,所以它切换到uint64

>>> np.array([2**64-1, 2**63-1]).dtype
dtype('float64')

现在我添加了一些其他的数字,它也完全适合uint64,它突然变成了float64

>>> np.array([2**65-1]).dtype
dtype('O')

好的,2**65-1需要某种更大的整数表示。

>>> np.array([2**64-1, 2**65-1]).dtype
dtype('O')

这不仅奇怪,而且还影响精度:

>>> int(np.round(np.array([2**64-1])[0]))
18446744073709551615
>>> int(np.round(np.array([2**64-1, 2**63-1])[0]))
18446744073709551616
>>> int(np.round(np.array([2**64-1, 2**65-1])[0]))
18446744073709551615

在这三个表达式中,第一个和第三个被计算而不损失精度,但是第二个由于转换为float并返回到int而被舍入。为什么第二个表达式使用浮点数,而完全精确的整数类型显然是可用的?

kxe2p93d

kxe2p93d1#

这是一个已知的问题,NumPy issue 19146。(我不确定它是否越过了被称为bug的界限,但它肯定是一个问题。)看起来几年前可能已经做出了一些努力来改变这种行为,但看起来并没有发生任何事情。
NumPy的uint64处理有很多这样的尴尬情况。没有足够大的整数dtype来容纳uint64 dtype和任何有符号dtype的所有值,因此当操作较小的dtype时,将提升为更大的整数dtype的代码将提升为float64。在尝试做基本算术时也会出现类似的尴尬:

In [1]: import numpy

In [2]: numpy.uint64(1) + 1  # float64 result!
Out[2]: 2.0

In [3]: numpy.uint64(1) << 1  # error!
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [3], in <cell line: 1>()
----> 1 numpy.uint64(1) << 1

TypeError: ufunc 'left_shift' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

相关问题