Java:创建数组的副本而不引用它

Orr*_*vid 2 java arrays copy matrix pass-by-reference

我编写了一系列矩阵运算,其中我使用二维浮点数组,将其视为矩阵,然后对其进行矩阵运算以获得逆。我的问题是,尽管我与类方法一起使用的数组不是类的一部分,但是每次我以数组为参数运行该方法时,数组本身也会被修改。

首先,我将描述如何得到矩阵的逆,然后将显示输出。

求矩阵逆的步骤如下:

  1. 获取辅因子矩阵(即,创建原始矩阵的矩阵次矩阵,然后取反其他项。如果C =辅因子矩阵,M =次要矩阵,i是当前行,j是当前列,则C [i] [j] = M [i] [j] *(-1)^(i + j)
  2. 通过转置(代换行,列条目的类似列,行条目,反之亦然)辅因子矩阵,将辅因子矩阵转换为辅助(也称为伴随)矩阵。如果C =辅因子矩阵,A =佐剂矩阵,i是当前行,j是当前列,则A [i] [j] = C [j] [i]
  3. 最后,取原始矩阵的一个超行列式,然后将辅助矩阵乘以该值。如果I =逆矩阵,A =佐证矩阵和D =行列式,则I =(1 / D)* A
  4. 为了测试您是否真正获得了矩阵的矩阵逆,可以将原始矩阵乘以它的逆得到恒等矩阵。如果I =逆,O =原始矩阵,并且id =单位矩阵,则O * I = id

现在,我将在实现这些操作的地方展示代码。为了简洁起见,我不会描述如何获取未成年人矩阵或行列式,但是无论如何我都会遇到的问题将变得显而易见。

public class MatrixOperations {
    //Note: this method works fine. There are no problems.
    public float determinant(float [][] a)
    {
        float [][] temp_mat;
        float res = 0;
        //assuming a square matrix
        /*If it's a 2X2, then use the formula for a determinant of
        2X2 matrices.*/
        if(a.length == 2)
        {
            return a[0][0]*a[1][1]-a[0][1]*a[1][0];
        }
        /*Otherwise do the determinant formula recursively until your
        determinant is made up of 2X2 matrix determinants and scalar products*/
        else
        {
            temp_mat = new float[a.length-1][a.length-1];
            int placej = 0;
            int placei = 0;
            for(int k = 0; k<a.length;k++)
            {
                for(int j = 0; j<a.length; j++)
                {
                    for(int i = 1; i < a.length; i++)
                    {
                        placei = i-1;

                        if(j != k)
                        {
                            if(j < k)
                            {
                                temp_mat[placei][j] = a[i][j];
                            }
                            else if(j > k)
                            {
                                if (i == 1){
                                    placej = j-1;
                                }
                                temp_mat[placei][placej] = a[i][j];
                            }
                        }
                    }
                }

                res+=a[0][k]*determinant(temp_mat)*(int)Math.pow(-1, k);
            }
            return res;
        }
    }
    //Note: this method also works fine
    //Scalar product method
    public float[][] mul(float[][] m, float r)
    {
        float[][] res = new float[m.length][m.length];

        for(int i = 0; i < m.length; i++)
        {
            for(int j = 0; j < m.length; j++)
            {
                res[i][j]= m[i][j]*r;
            }
        }

        return res;

    }
    //Note: This method also works fine
    public float[][] mul(float[][] m,float[][] n)
    {
        float[][] res = new float[m.length][m.length];

        for(int i = 0; i < m.length; i++)
        {
            for(int j = 0; j < m.length; j++)
            {
                for(int k = 0; k < m.length; k++)
                {
                    res[i][j] += m[i][k]*m[k][i];
                }
            }
        }

        return res;

    }
    //The method for creating a matrix of minors
    //Here I start having problems
    public float[][] minor(float [][] m)
    {
        float [][] minor_mat = new float [m.length][m.length];
        //If the matrix is greater than a 2X2, use this to generate a matrix of minors
        if(m.length > 2)
        {
            float [][] current_minor = new float [m.length-1][m.length-1];
            int placei = 0;
            int placej = 0;
            for(int i = 0; i < m.length; i++)
            {
                for(int j = 0; j < m.length; j++)
                {
                    for(int k = 0; k < m.length; k++)
                    {
                        for(int l = 0; l < m.length; l++)
                        {
                            if(i != k && j != l)
                            {
                                if(k<i)
                                    placei = k;
                                else if(k>i)
                                    placei = k-1;
                                if(l<j)
                                    placej = l;
                                else if(l>j)
                                    placej = l-1;

                                current_minor[placei][placej] = m[k][l];
                            }
                        }
                    }
                    minor_mat[i][j] = this.determinant(current_minor);
                }
            }
        }
        //otherwise use the definition for 2X2 matrix of minors
        else
        {
            //even though minor_mat is using m.clone() rather than m, when I return the result, m has still been modified for some reason.
            minor_mat = m.clone()
            float temp;
            temp = minor_mat[0][0];
            minor_mat[0][0] = minor_mat[1][1];
            minor_mat[1][1] = temp;
            temp = minor_mat[0][1];
            minor_mat[0][1] = minor_mat[1][0];
            minor_mat[1][0] = temp;
        }
        return minor_mat;
    }
    //the same problem occurs here as it did in the minor method
    //m appears to get modified even though I only use m.clone()
    public float[][] cofactor(float [][] m)
    {
        float[][] res = m.clone();
        res = this.minor(res)
        for(int i = 0; i < m.length; i++)
        {
            for(int j = 0; j < m.length; j++)
            {
                res[i][j] = res[i][j]*(int)Math.pow(-1, i + j);
            }
        }
        return res;
    }

    //The following transpose, adjugate, and inverse methods have the same problem        

    public float[][] transpose(float[][] m)
    {
        float[][] res = new float[m.length][m.length];
        float temp = 0;
        for(int i = 0; i < m.length; i++)
        {
            for(int j = 0; j < m.length; j++)
            {
                temp = m[i][j];
                res[i][j] = m[j][i];
                res[j][i] = temp;       
            }
        }
        return res;
    }
    public float[][] adjugate(float[][] m)
    {
        float[][] res = this.transpose(this.cofactor(m));
        return res;
    }
    public float[][] inverse(float[][] m)
    {
        float[][] res = this.mul(this.adjugate(m), (1/this.determinant(m)));
        return res;
    }
    //print out the matrix in square form
    public void matrixprint(float [][] m)
    {
        for(int i = 0; i < m.length; i++)
        {
            System.out.println("");
            for(int j = 0; j < m[i].length; j++){
                System.out.print(m[i][j] + " ");
            }
        }
        System.out.println("\n");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,主类和main方法创建MatrixOperations类的实例,并在2X2矩阵上使用其方法。

public class Main {

    public static void main(String[] args) {
        MatrixOperations mo = new MatrixOperations();

        //Create a 2X2 matrix called "matrix" and set its elements
        //Then perform each step on "matrix" and finally test if you have acquired the correct inverse

        float [][] matrix = new float[2][2];
        matrix[0][0] = 2;
        matrix [0][1] = 5;
        matrix [1][0] = 4;
        matrix [1][1] = 3;

        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Minor = ");
        mo.matrixprint(mo.minor(matrix));
        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Cofactor = ");
        mo.matrixprint(mo.cofactor(matrix));
        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Adjugate = ");
        mo.matrixprint(mo.adjugate(matrix));
        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Determinant = ");
        System.out.println(mo.determinant(matrix));
        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Inverse = ");
        mo.matrixprint(mo.inverse(matrix));
        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Identity = ");
        mo.matrixprint(mo.mul(mo.inverse(matrix), matrix));

    }

}
Run Code Online (Sandbox Code Playgroud)

现在,您将看到显示输出时,每次我在“矩阵”上使用一种方法并重新打印“矩阵”时,即使我的方法仅使用“矩阵”的副本而不是“矩阵”本身。

输出:

Matrix = 

2.0 5.0 
4.0 3.0 

Minor = 

3.0 4.0 
5.0 2.0 

Matrix = 

3.0 4.0 
5.0 2.0 

Cofactor = 

3.0 -4.0 
-5.0 2.0 

Matrix = 

3.0 -4.0 
-5.0 2.0 

Adjugate = 

3.0 5.0 
4.0 2.0 

Matrix = 

3.0 4.0 
5.0 2.0 

Determinant = 
-14.0
Matrix = 

3.0 4.0 
5.0 2.0 

Inverse = 

-0.21428573 0.35714287 
0.2857143 -0.14285715 

Matrix = 

3.0 -4.0 
-5.0 2.0 

Identity = 

0.1479592 0.1479592 
0.12244898 0.12244898
Run Code Online (Sandbox Code Playgroud)

任何帮助/解释为什么会发生这种情况将不胜感激。

Pet*_*rey 5

这条线是浅表克隆。

float[][] res = m.clone();
Run Code Online (Sandbox Code Playgroud)

这会将reswhich是对数组的引用数组。但没有任何数组res指向。您最想要的是

float[][] res = new float[m.length][];
for (int i = 0; i < m.length; i++)
    res[i] = m[i].clone();
Run Code Online (Sandbox Code Playgroud)