You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用JAMA库计算矩阵逆结果错误的排查与解决咨询

问题分析与解决思路

你的代码本身没有语法错误,但核心问题不是int转double的过程——真正的问题是:你在密码学场景中需要的是模运算(通常是模26,对应字母表)下的矩阵逆,而JAMA库的inverse()方法计算的是实数域上的普通矩阵逆,这完全是两个不同的概念,所以结果不符合你的需求。

为什么普通逆没用?

密码学中的密钥矩阵逆要求所有元素都是整数,且满足原矩阵和逆矩阵相乘后,结果矩阵的每个元素模26等于单位矩阵的对应元素(即对角线为1,其余为0)。而你现在得到的是小数形式的实数逆,显然不符合密钥场景的要求。

解决步骤

要计算模运算下的整数矩阵逆,需要按以下逻辑实现:

  1. 计算原矩阵的行列式,并验证该行列式与模数(比如26)互质(最大公约数为1),只有这样矩阵在模下才可逆。
  2. 计算行列式的模逆:找到一个整数x,使得(行列式 * x) ≡ 1 mod 模数。
  3. 计算原矩阵的伴随矩阵,将伴随矩阵的每个元素乘以行列式的模逆,再对模数取余,得到最终的整数逆矩阵。

针对你的密钥矩阵的具体实现

以模数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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 11:30:37