矩陣運算, 每次遇到這個問題就頭痛想半天, 要搞這個就要先理解術語
台灣跟大陸定義剛好是反過來, 看得很煩躁
m = row = y = height = 高 = 列 = 行(簡)
n = column = x = width = 寬 = (欄/行) = 列(簡)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| height = len(matrix) # y 的最大範圍 (Rows) width = len(matrix[0]) # x 的最大範圍 (Cols)
for y in range(height): # 外層跑垂直高度 (y 方向) for x in range(width): # 內層跑水平寬度 (x 方向) # 注意:矩陣存取通常是 [y][x] print(f"座標 ({x}, {y}) 的值為: {matrix[y][x]}")
rows = len(matrix) cols = len(matrix[0])
for i in range(rows): for j in range(cols): print(matrix[i][j])
|
搞定術語後就可以進入正題
可以參考這裡 mathsisfun
或是用這個線上工具來算 matrixmultiplication
(1, 2, 3) • (7, 9, 11)= 1×7 + 2×9 + 3×11 = 58
(1, 2, 3) • (8, 10, 12) = 1×8 + 2×10 + 3×12 = 64
(4, 5, 6) • (7, 9, 11) = 4×7 + 5×9 + 6×11 = 139
(4, 5, 6) • (8, 10, 12) = 4×8 + 5×10 + 6×12 = 154
關鍵在於先把解答矩陣大小算出來
A (2 * 3) = 2 h * 3 w
B (3 * 2) = 3 h * 2 w
只取 A 的 h 跟 B 的 w
C (2 * 2) = C(Ay * Bx)
所以這裡會得到一個 m = 2, n 也 = 2 的 matrix
計算時跟平時操作 2d array 一樣, aWidth 等於就是次數
第三個迴圈是這題另外一個關鍵, 他第一次會長這樣以此類推
C[0][0] += A[0][0] * B[0][0] //17
C[0][0] += A[0][1] * B[1][0] //29
C[0][0] += A[0][2] * B[2][0] //3*11
結果為 58
C[0][1] += A[0][0] * B[0][1] //18
C[0][1] += A[0][1] * B[1][1] //210
C[0][1] += A[0][2] * B[1][1] //3*12
結果為 64
最後要注意到矩陣維度問題
(3,2) * (3,2) not work
(2,3) * (3,2) work
(3,2) * (2,3) work
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| let A = [ [1,2,3], [4,5,6] ]
let B = [ [7,8], [9,10], [11,12], ]
ay = aHeight = A.length ax = aWidth = A[0].length by = bHeight = B.length bx = bWidth = B[0].length
console.log(`ay ${ay}`) console.log(`ax ${ax}`) console.log(`by ${by}`) console.log(`bx ${bx}`)
let C = [] for (let y = 0; y < ay; y++) { C[y] = [] for (let x = 0; x < bx; x++) { C[y][x] = 0 } }
//立即列印, 防止 chrome 之後印參考 console.log(JSON.stringify(C))
/* let C = [ [0,0], [0,0], ] */
//計算結果 for(let y = 0; y < aHeight; y++){ for(let x = 0; x < bWidth; x++){ for(let z = 0; z < aWidth; z++){ C[y][x] += A[y][z] * B[z][x] } } }
/* C[0][0] += A[0][0] * B[0][0] //1*7 C[0][0] += A[0][1] * B[1][0] //2*9 C[0][0] += A[0][2] * B[2][0] //3*11 結果為 58
C[0][1] += A[0][0] * B[0][1] //1*8 C[0][1] += A[0][1] * B[1][1] //2*10 C[0][1] += A[0][2] * B21][1] //3*12 結果為 64 */
console.log(C)
|
偷懶用 chatgpt 搞成 python XD
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| # 定義矩陣 A = [ [1, 2, 3], [4, 5, 6] ]
B = [ [7, 8], [9, 10], [11, 12] ]
# 矩陣尺寸 aHeight = len(A) aWidth = len(A[0]) bHeight = len(B) bWidth = len(B[0])
print(f"ay {aHeight}") print(f"ax {aWidth}") print(f"by {bHeight}") print(f"bx {bWidth}")
# 初始化結果矩陣 C C = [[0 for _ in range(bWidth)] for _ in range(aHeight)]
# 立即列印,防止引用問題 import json print(json.dumps(C))
# 計算結果 for y in range(aHeight): for x in range(bWidth): for z in range(aWidth): C[y][x] += A[y][z] * B[z][x]
print(C)
|
順帶一提要算 dot product 可以這樣寫
1 2 3 4 5 6 7 8 9 10 11 12 13
| A = [[0, 3, 2], [-3, -3, 1], [1, 0, 2]]
B = [[1, 0, 6], [2, -1, 0], [5, 1, 4]]
total = 0 for y in range(len(A)): for x in range(len(A[0])): total += A[y][x] * B[y][x] print(f"{A[y][x] * B[y][x]:>2} ", end="") print()
print() print(f"total:{total}")
|