HOWTO · NumPy
Python NumPy 中的逐元素除法
有两种主要方法可用于在 Python 中对 NumPy 数组执行逐元素除法,即 numpy.divide() 函数和 / 运算符。
本页内容
要对 NumPy 数组中对应位置的值相除,可以使用 numpy.divide(x1, x2) 或 x1 / x2。两种写法都会逐元素执行真除法并返回一个数组;如果需要用 out 或 where 等可选参数控制结果,可以选择函数形式。
使用 numpy.divide()
numpy.divide() 的第一个参数是被除数,第二个参数是除数。两个数组形状相同时,第一个数组中的每个值都会除以第二个数组相同位置的值。如果之后还要使用返回的数组,请将它赋给一个变量。out 参数是可选的:省略它时,NumPy 会创建并返回结果;如果要将结果写入已有数组,则传入形状和数据类型兼容的数组。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
import numpy as np
numerators = np.array([12, 18, 24])
denominators = np.array([3, 6, 8])
by_function = np.divide(numerators, denominators)
destination = np.array([0.0, 0.0, 0.0])
np.divide(numerators, denominators, out=destination)
by_operator = numerators / denominators
print(by_function)
print(by_operator)
print(destination)
[4. 3. 3.]
[4. 3. 3.]
[4. 3. 3.]
第一次调用函数时省略了 out,因此会返回新创建的数组。第二次调用会将结果写入 destination;这个数组已按结果所需的形状和数据类型创建。运算符使用相同的输入,因此三个数组中的商都相同。输入是整数,而真除法会产生浮点数值。
使用 / 运算符
在大多数表达式中,/ 是对 NumPy 数组逐元素相除时最简洁明了的写法。可以写成 result = numerators / denominators;运算会按位置逐项进行,结果数组可以赋给变量、用于索引,或传给其他 NumPy 运算。当某个操作数是标量,或两个数组的形状兼容时,NumPy 会按照数组运算规则处理。
/ 并不是单独的整数除法运算:对于整数数组,它会执行真除法,商以浮点数表示。这与 Python 的 // 不同,后者执行向下取整除法。应根据所需运算选择运算符;需要保留小数商时,不要使用 //。
广播、数据类型与零除数
形状相同的数组会直接对对应元素相除。NumPy 也支持兼容形状之间的广播:从最右侧维度开始比较,每一对维度必须相等,或其中一个维度为 1。例如,形状为 (2, 3) 的二维数组可以除以形状为 (3,) 的一维数组,这会将每个除数应用到每一行。如果形状不符合广播规则,就无法逐元素相除;遇到形状不匹配时,请检查两个操作数的 array.shape。
结果的数据类型取决于输入的数据类型以及除法运算。具体来说,整数输入使用 / 或 numpy.divide() 时会得到真除法结果,不会将每个商截断为整数。如果后续步骤需要特定的数据类型,请在除法后有意进行转换,并考虑转换是否会丢失小数部分。
对于真除法,/ 和 numpy.divide() 对整数输入都会产生浮点数结果。因此,除数为零时,非零被除数可能得到无穷大,而 0 / 0 会得到 nan,并伴随运行时警告;浮点数输入也可能出现这些情况。本文介绍的是这些真除法形式;使用 // 的向下取整除法属于不同运算,不在此范围内。如果要排除除数为零的位置,请先初始化输出数组,再使用 numpy.divide(a, b, out=result, where=b != 0);条件为假的位置会保留已初始化的值。请选择适合后续计算的填充值,并另外决定如何处理这些被排除的位置。
如何选择除法写法
如果只需要简洁地表达逐元素相除,请使用 /。如果需要利用函数参数,尤其是将结果写入已有数组的 out,或用 where 选择要计算的位置,请使用 numpy.divide()。无论采用哪种写法,都要确认操作数的形状兼容,并根据数据类型决定如何处理零除数。做好这些检查后,代码就更容易适用于向量、矩阵和可广播的输入。