Strassen矩阵乘法算法报错求助:解决数组越界异常
Strassen矩阵乘法算法Java代码错误排查及修复
核心错误分析
抛出ArrayIndexOutOfBoundsException: Index 2 out of bounds for length 2的主要原因如下:
- 结果矩阵初始化错误:
mulMatx方法中,仅当矩阵阶数n=1时才正确初始化结果矩阵,当n>1时,C始终是1×1的矩阵。在后续合并子矩阵(joinMatx)时,尝试访问C[2][2]这类超出1×1范围的索引,直接触发越界异常。 - 矩阵拆分逻辑颠倒:
splitMatx方法的赋值逻辑完全反向,原本应该将主矩阵的子区域数据复制到子矩阵中,但代码写成了mainMat[i1][j1] = subMat[i2][j2],导致子矩阵始终是默认值0,且错误修改了原矩阵数据。 - 矩阵合并参数顺序错误:
joinMatx方法的参数传递顺序与内部逻辑不匹配,方法内部是将第一个参数的内容写入第二个参数,但实际调用时传入的是子矩阵在前、结果矩阵在后,导致无法正确合并结果。 - 矩阵加减方法的数组初始化问题:
addMatx和subMatx中创建结果矩阵时使用new int[A.length][B.length],虽然测试用例是方阵,但逻辑上应该保持行列数与输入矩阵一致,应改为new int[A.length][A.length](因Strassen算法仅适用于同阶方阵)。
修复后的完整代码
import java.util.*; public class Main { public static int[][] mulMatx(int[][] A, int[][] B) { int n = A.length; // 初始化结果矩阵为n×n,而非固定1×1 int[][] C = new int[n][n]; if (n == 1) { C[0][0] = A[0][0] * B[0][0]; } else { int half = n / 2; // 子矩阵初始化 int[][] A11 = new int[half][half]; int[][] A12 = new int[half][half]; int[][] A21 = new int[half][half]; int[][] A22 = new int[half][half]; int[][] B11 = new int[half][half]; int[][] B12 = new int[half][half]; int[][] B21 = new int[half][half]; int[][] B22 = new int[half][half]; // 拆分主矩阵到子矩阵(修复后的逻辑) splitMatx(A, A11, 0, 0); splitMatx(A, A12, 0, half); splitMatx(A, A21, half, 0); splitMatx(A, A22, half, half); splitMatx(B, B11, 0, 0); splitMatx(B, B12, 0, half); splitMatx(B, B21, half, 0); splitMatx(B, B22, half, half); // Strassen的7个中间乘积计算 int[][] M1 = mulMatx(addMatx(A11, A22), addMatx(B11, B22)); int[][] M2 = mulMatx(addMatx(A21, A22), B11); int[][] M3 = mulMatx(A11, subMatx(B12, B22)); int[][] M4 = mulMatx(A22, subMatx(B21, B11)); int[][] M5 = mulMatx(addMatx(A11, A12), B22); int[][] M6 = mulMatx(subMatx(A21, A11), addMatx(B11, B12)); int[][] M7 = mulMatx(subMatx(A12, A22), addMatx(B21, B22)); // 计算结果矩阵的四个象限 int[][] C11 = addMatx(subMatx(addMatx(M1, M4), M5), M7); int[][] C12 = addMatx(M3, M5); int[][] C21 = addMatx(M2, M4); int[][] C22 = addMatx(subMatx(addMatx(M1, M3), M2), M6); // 合并子矩阵到结果矩阵(修复参数顺序后的调用) joinMatx(C, C11, 0, 0); joinMatx(C, C12, 0, half); joinMatx(C, C21, half, 0); joinMatx(C, C22, half, half); } return C; } // 修复拆分逻辑:将主矩阵的子区域复制到子矩阵 public static void splitMatx(int[][] mainMat, int[][] subMat, int startRow, int startCol){ int subSize = subMat.length; for(int i = 0; i < subSize; i++){ for(int j = 0; j < subSize; j++){ subMat[i][j] = mainMat[startRow + i][startCol + j]; } } } // 修复合并逻辑:将子矩阵复制到主矩阵的指定位置 public static void joinMatx(int[][] mainMat, int[][] subMat, int startRow, int startCol){ int subSize = subMat.length; for(int i = 0; i < subSize; i++){ for(int j = 0; j < subSize; j++){ mainMat[startRow + i][startCol + j] = subMat[i][j]; } } } public static int[][] addMatx(int[][] A, int[][] B){ int n = A.length; int[][] C = new int[n][n]; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { C[i][j] = A[i][j] + B[i][j]; } } return C; } public static int[][] subMatx(int[][] A, int[][] B){ int n = A.length; int[][] C = new int[n][n]; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { C[i][j] = A[i][j] - B[i][j]; } } return C; } public static void printMatx(int[][] Mat) { for(int[] row : Mat){ System.out.println(Arrays.toString(row)); } } public static void main(String[] args) { int[][] matA = { {2, 4, 5, 9}, {2, 12, 7, 5}, {15, 8, 2, 5}, {14, 4, 2, 5} }; int[][] matB = { {7, 4, 2, 24}, {15, 7, 2, 6}, {10, 12, 2, 4}, {9, 2, 6, 3} }; printMatx(mulMatx(matA, matB)); } }
关键修复点说明
- 结果矩阵初始化:将
int[][] C = new int[1][1];改为int[][] C = new int[n][n];,确保结果矩阵的大小与输入矩阵一致。 - 拆分方法逻辑修正:
splitMatx中把赋值方向反转,从主矩阵的startRow+i和startCol+j位置取值,赋值给子矩阵的i,j位置。 - 合并方法参数与逻辑匹配:调整
joinMatx的参数顺序为(结果矩阵,子矩阵,起始行,起始列),并修正内部赋值逻辑,将子矩阵的数据写入结果矩阵的对应区域。 - 矩阵加减方法的数组初始化:统一使用
n×n的大小创建结果矩阵,保持与输入方阵的一致性。
内容的提问来源于stack exchange,提问作者Krit Vardhan Mishra
相关产品推荐
相关产品推荐

