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()。無論使用哪種方式,都要確認運算元的形狀相容,並依照資料的型別決定如何處理除數為零的情況。做好這些檢查後,程式碼便更容易套用到向量、矩陣和可廣播的輸入。