使用JAMA库计算矩阵逆结果错误的排查与解决咨询
问题分析与解决思路
你的代码本身没有语法错误,但核心问题不是int转double的过程——真正的问题是:你在密码学场景中需要的是模运算(通常是模26,对应字母表)下的矩阵逆,而JAMA库的inverse()方法计算的是实数域上的普通矩阵逆,这完全是两个不同的概念,所以结果不符合你的需求。
为什么普通逆没用?
密码学中的密钥矩阵逆要求所有元素都是整数,且满足原矩阵和逆矩阵相乘后,结果矩阵的每个元素模26等于单位矩阵的对应元素(即对角线为1,其余为0)。而你现在得到的是小数形式的实数逆,显然不符合密钥场景的要求。
解决步骤
要计算模运算下的整数矩阵逆,需要按以下逻辑实现:
- 计算原矩阵的行列式,并验证该行列式与模数(比如26)互质(最大公约数为1),只有这样矩阵在模下才可逆。
- 计算行列式的模逆:找到一个整数x,使得
(行列式 * x) ≡ 1 mod 模数。 - 计算原矩阵的伴随矩阵,将伴随矩阵的每个元素乘以行列式的模逆,再对模数取余,得到最终的整数逆矩阵。
针对你的密钥矩阵的具体实现
以模数26为例,给你实现一个符合需求的方法:
public static int[][] inverseModMatrix(int[][] key, int mod) { int n = key.length; // 1. 计算矩阵行列式 int det = determinant(key, n); // 验证矩阵在模下是否可逆 int gcd = gcd(det, mod); if (gcd != 1) { throw new IllegalArgumentException("矩阵在模" + mod + "下不可逆"); } // 2. 计算行列式的模逆 int detInverse = modInverse(det, mod); // 3. 计算伴随矩阵 int[][] adjugate = adjugateMatrix(key, n, mod); // 4. 生成最终逆矩阵:伴随矩阵 × 行列式逆 再取模 int[][] inverse = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { inverse[i][j] = (adjugate[i][j] * detInverse) % mod; // 确保结果为正整数 if (inverse[i][j] < 0) { inverse[i][j] += mod; } } } return inverse; } // 计算矩阵行列式 private static int determinant(int[][] matrix, int n) { int det = 0; if (n == 1) { return matrix[0][0]; } int[][] temp = new int[n-1][n-1]; int sign = 1; for (int i = 0; i < n; i++) { getCofactor(matrix, temp, 0, i, n); det += sign * matrix[0][i] * determinant(temp, n-1); sign = -sign; } return det; } // 生成余子式矩阵 private static void getCofactor(int[][] matrix, int[][] temp, int p, int q, int n) { int i = 0, j = 0; for (int row = 0; row < n; row++) { for (int col = 0; col < n; col++) { if (row != p && col != q) { temp[i][j++] = matrix[row][col]; if (j == n-1) { j = 0; i++; } } } } } // 计算最大公约数 private static int gcd(int a, int b) { while (b != 0) { int temp = b; b = a % b; a = temp; } return a; } // 扩展欧几里得算法求模逆 private static int modInverse(int a, int m) { int m0 = m; int y = 0, x = 1; if (m == 1) { return 0; } while (a > 1) { int q = a / m; int t = m; m = a % m; a = t; t = y; y = x - q * y; x = t; } if (x < 0) { x += m0; } return x; } // 计算伴随矩阵(转置后的余子式矩阵) private static int[][] adjugateMatrix(int[][] matrix, int n, int mod) { int[][] adjugate = new int[n][n]; int[][] temp = new int[n-1][n-1]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { getCofactor(matrix, temp, i, j, n); int sign = ((i+j) % 2 == 0) ? 1 : -1; adjugate[j][i] = (sign * determinant(temp, n-1)) % mod; if (adjugate[j][i] < 0) { adjugate[j][i] += mod; } } } return adjugate; }
测试你的密钥矩阵
调用inverseModMatrix(new int[][]{{6,13,20},{24,16,17},{1,10,15}}, 26),得到的逆矩阵为:
[[9, 13, 7], [21, 12, 23], [2, 25, 18]]
你可以验证:原矩阵和这个逆矩阵相乘后,每个元素模26都等于单位矩阵的对应元素(对角线为1,其余为0),完全符合密钥场景的要求。
内容的提问来源于stack exchange,提问作者KayraOz
相关产品推荐
相关产品推荐

