【发布时间】:2020-03-31 09:32:18
【问题描述】:
假设我有一个非常大的值数组,介于 1 和 180 之间,这些值位于 uint8s 的数组中(最高可达 255)。我想为每个值加上 90(模 180):
original = np.array([1, 2, 3, 170, 171, 172], dtype=np.uint8)
modified = (original + 90) % 180
不幸的是,这会产生不正确的结果,因为在添加 90 时,较大的数字会在第一步中溢出它们的 uint8 整数:170 + 90 = 260,它大于 255。
# (170 + 90) % 180 is 80, not 4 :(
array([91, 92, 93, 4, 5, 6], dtype=uint8)
我在对性能非常敏感的环境中操作,我的输入列表非常大。因此,我想避免将此数组转换为更大数据类型的惩罚,并且我想使用高效的操作(例如,避免循环遍历数组并单独处理每个值)。
我怎样才能做到这一点?
【问题讨论】:
-
使用
import numpy和numpy.mod(numpy1arr + 90, numpy2arr)。在您的情况下,我假设 numpy2arr 将是 180 的 n 向量。 -
>>> ((original.astype(np.uint16) + 90) % 180).astype(np.uint8) array([91, 92, 93, 80, 81, 82], dtype=uint8)?或者你不想投射? -
@furkanayd:这会产生相同的问题,因为溢出发生在
numpy1arr + 90步骤中。 -
@GiacomoAlzetta 感谢您的建议,这将产生正确的结果。然而,正如我在描述中提到的,这个数组非常大,转换为更大的数据类型非常昂贵。
-
这是一个有趣的问题,尽管出于实际目的,请记住创建多个中间数组(掩码、每个操作等)的解决方案可能比向上转换(最终只需要如果您重用原始数组来存储向下转换的结果,则为 16 位的原始大小的两倍)。高级索引(选择带有掩码的数组子集)也很昂贵。我将这里的解决方案与简单的向上转换解决方案进行基准测试。
标签: python arrays numpy modulo