【问题标题】:Error with numpy array calculations using int dtype (it fails to cast dtype to 64 bit automatically when needed)使用 int dtype 计算 numpy 数组时出错(它无法在需要时自动将 dtype 转换为 64 位)
【发布时间】:2020-02-21 03:14:38
【问题描述】:

当计算的输入是具有 32 位整数数据类型的 numpy 数组,但输出包含需要 64 位表示的较大数字时,我遇到了不正确的 numpy 计算问题。

这是一个最小的工作示例:

arr = np.ones(5, dtype=int) * (2**24 + 300)  # arr.dtype defaults to 'int32'

# Following comment from @hpaulj I changed the first line, which was originally:
# arr = np.zeros(5, dtype=int) 
# arr[:] = 2**24 + 300

single_value_calc = 2**8 * (2**24 + 300)
numpy_calc = 2**8 * arr

print(single_value_calc)
print(numpy_calc[0])

# RESULTS
4295044096
76800

想要的输出是 numpy 数组包含正确的值 4295044096,这需要 64 位来表示它。即,我希望 numpy 数组在输出需要时自动从 int32 向上转换为 int64,而不是保持 32 位输出并在超过 2^32 的值后返回 0。

当然,我可以通过强制 int64 表示来手动解决问题:

numpy_calc2 = 2**8 * arr.astype('int64')

但这对于一般代码来说是不可取的,因为在某些情况下输出只需要 64 位表示(即保存大数字)而不是全部。在我的用例中,性能至关重要,因此每次都强制向上转换成本很高。

这是 numpy 数组的预期行为吗?如果是这样,请问有没有干净、高效的解决方案?

【问题讨论】:

  • 强制转换的是arr[:]= 赋值,你不能那样改变数组的dtype。看看如果将浮点数分配给 tgat 数组会发生什么。
  • 感谢您的评论,尽管该行不是应该进行转换的地方。这是我想要 64 位输出的“numpy_calc = ...”行。例如,我可以删除 [:] 操作,问题仍然存在(参见修改后的帖子)。

标签: python arrays numpy integer numpy-ndarray


【解决方案1】:

numpy 中的类型转换和提升是相当复杂的,有时令人惊讶。 This recent unofficial write-up by Sebastian Berg 解释了该主题的一些细微差别(主要集中在标量和 0d 数组上)。

引用本文档:

Python 整数和浮点数

请注意,python 整数的处理方式与 numpy 完全相同。然而,它们的特殊之处在于它们没有明确关联的 dtype。如此处所述,基于值的逻辑似乎对 python 整数和浮点数很有用:

arr = np.arange(10, dtype=np.int8)
arr += 1
# or:
res = arr + 1
res.dtype == np.int8

确保不会发生向上转换(例如内存使用量较高)。

(强调我的。)

另见Allan Haldane's gist suggesting C-style type coercion,链接自上一个文档:

目前,当一个二元运算涉及两个 dtype 时,numpy 的原则是“输出 dtype 的范围覆盖两个输入 dtype 的范围”,当涉及单个 dtype 时,从不进行任何转换。强>

(再次强调我的。)

所以我的理解是 numpy 标量和数组的提升规则不同,主要是因为检查数组中的每个元素以确定是否可以安全地进行转换是不可行的。再次来自以前的文档:

基于标量的规则

与无法检查所有值的数组不同,对于标量(和 0-D 数组),检查值。

这意味着您可以从一开始就使用 np.int64 以确保安全(如果您在 linux 上,那么 dtype=int 实际上会自行执行此操作),或者在之前检查数组的最大值怀疑操作,并根据具体情况确定您是否必须自己提升 dtype。我知道如果您进行大量计算,这可能不可行,但考虑到 numpy 当前的类型提升规则,我认为没有办法解决这个问题。

【讨论】:

  • 感谢您的详细解释 - 这确实有道理。提供一个“启用转换/检查标志”当然是 numpy 数组的一个很好的特性,它可以检查是否即使是标量乘法也需要这种转换,但我接受这种行为比它更频繁地“不想要” '想要'。
  • @SLhark 确实如此。值得一提的是,链接文档的出现正是因为建议更改促销行为,尽管我怀疑不检查数组元素的理念足够基本,即使最终进行了一些更改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 2017-01-20
  • 2021-09-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多