Java:创建数组的副本而不将其作为引用

时间:2016-04-08 18:34:24

标签: java arrays matrix copy pass-by-reference

我编写了一系列矩阵运算,其中我采用二维浮点数组,将其视为矩阵,并对其执行矩阵运算以获取逆运算。我的问题是虽然我使用类方法的数组不是类的一部分,但每次我以数组作为参数运行方法时,数组本身也会被修改。

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

采用矩阵的逆矩阵的步骤如下:

  1. 获取辅助因子矩阵(即创建原始矩阵的矩阵未成像矩阵,然后否定所有其他条目。如果C = Cofactor矩阵,M =未成年人矩阵,i是当前行,j是当前列,然后 C [i] [j] = M [i] [j] *(-1)^(i + j)
  2. 通过将辅因子矩阵转置(将行,列条目替换为其类似列,行条目,反之亦然),将辅因子矩阵转换为adjugate(也称为adjoint)矩阵。如果C = Cofactor Matrix,A = Adjugate Matrix,i是当前行,j是当前列,则 A [i] [j] = C [j] [i]
  3. 最后,取一个原始矩阵的行列式,并将该调整矩阵乘以该值。如果I =逆矩阵,A =仲裁矩阵,D =行列式,那么 I =(1 / D)* A
  4. 为了测试您是否真正获得了矩阵的矩阵求逆,可以将原始矩阵乘以其逆以获得单位矩阵。 如果I = Inverse,O = Original Matrix,id = Identity Matrix,则 O * I = id
  5. 现在我将介绍实现这些操作的代码。为了简明起见,我不会描述如何获得未成年人矩阵或行列式,但我遇到的问题无论如何都会变得明显。

    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");
        }
    }
    

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

    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));
    
        }
    
    }
    

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

    输出:

    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
    

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

2 个答案:

答案 0 :(得分:0)

这是因为你在MatrixOperations类的方法中传递matrix对象的引用。它不是function setCookie(name, value) { var cookie = name + "=" + escape(value) + ";"; document.cookie = cookie; } $("#form1").submit(function(){ setCookie("input1", $("#input1").val()); // do this for all inputs }); 对象的副本。

来自Java doc

  

也会传入参考数据类型参数,例如对象   方法的价值。这意味着当方法返回时,   传入引用仍然引用与以前相同的对象。

答案 1 :(得分:0)

二维数组只是一个数组数组。 数组上的 <script> $(document).ready(function() { var max_fields = 10; //maximum input boxes allowed var wrapper = $(".dynamicinput"); //Fields wrapper var add_button = $(".add-more"); //Add button ID var x = 1; //initlal text box count $(add_button).click(function(e){ //on add input button click e.preventDefault(); if(x < max_fields){ //max input box allowed x++; //text box increment $(wrapper).append('<div class="col-md-4 col1"><div class="form-group"><label for="exampleInputEmail1"><strong>Name *</strong></label><input type="text" class="form-control textwidth" id="PersonalssDetails_firstname" class="AssignedEmergencyContacts_Name" name="AssignedEmergencyContacts_Name[]"><span><a href="#" class="remove_field">Remove</a></div>'); $(wrapper).append('<div class="col-md-4 col2"><div class="form-group"><label for="exampleInputEmail1"><strong>Relationship *</strong></label><input type="text" class="form-control textwidth" id="AssignedEmergencyContacts_Relationship" class="AssignedEmergencyContacts_Relationship" name="AssignedEmergencyContacts_Relationship[]"><span><a href="#" class="remove_field1">Remove</a></div>'); $(wrapper).append('<div class="col-md-4 col3"><div class="form-group"><label for="exampleInputEmail1"><strong>Home Telephone*</strong></label><input type="text" class="form-control textwidth" id="AssignedEmergencyContacts_HomeTelephone" class="AssignedEmergencyContacts_HomeTelephone" name="AssignedEmergencyContacts_HomeTelephone[]"><span><a href="#" class="remove_field2">Remove</a></div>'); $(wrapper).append('<div class="col-md-4 col4"><div class="form-group"><label for="exampleInputEmail1"><strong>Mobile *</strong></label><input type="text" class="form-control textwidth" id="AssignedEmergencyContacts_Mobile" class="AssignedEmergencyContacts_Mobile" name="AssignedEmergencyContacts_Mobile[]"><span><a href="#" class="remove_field3">Remove</a></div>'); $(wrapper).append('<div class="col-md-4 col5"><div class="form-group"><label for="exampleInputEmail1"><strong>Work Telephone *</strong></label><input type="text" class="form-control textwidth" id="AssignedEmergencyContacts_WorkTelephone" class="AssignedEmergencyContacts_WorkTelephone" name="AssignedEmergencyContacts_WorkTelephone[]"><span><a href="#" class="remove_field4">Remove</a></div>'); } }); $(wrapper).on("click",".remove_field", function(e){ //user click on remove text e.preventDefault(); $(this).parent('div').remove(); x--; }) }); </script> <div class="col-md-4"> <div class="form-group"> <label for="exampleInputEmail1"><strong>Name *</strong></label> <input type="text" class="form-control textwidth" id="PersonalssDetails_firstname" class="AssignedEmergencyContacts_Name" name="AssignedEmergencyContacts_Name[]"><span> </div> </div> <div class="col-md-4"> <div class="form-group"> <label for="exampleInputEmail1"><strong>Relationship *</strong></label> <input type="text" class="form-control textwidth" id="AssignedEmergencyContacts_Relationship" class="AssignedEmergencyContacts_Relationship" name="AssignedEmergencyContacts_Relationship[]"><span> </div> </div> <div class="col-md-4"> <div class="form-group"> <label for="exampleInputEmail1"><strong>Home Telephone* </strong></label> <input type="text" class="form-control textwidth" id="AssignedEmergencyContacts_HomeTelephone" class="AssignedEmergencyContacts_HomeTelephone" name="AssignedEmergencyContacts_HomeTelephone[]"><span> </div> </div> <div class="col-md-4"> <div class="form-group"> <label for="exampleInputEmail1"><strong>Mobile * </strong></label> <input type="text" class="form-control textwidth" id="AssignedEmergencyContacts_Mobile" class="AssignedEmergencyContacts_Mobile" name="AssignedEmergencyContacts_Mobile[]"><span> </div> </div> <div class="col-md-4"> <div class="form-group"> <label for="exampleInputEmail1"><strong>Work Telephone * </strong></label> <input type="text" class="form-control textwidth" id="AssignedEmergencyContacts_WorkTelephone" class="AssignedEmergencyContacts_WorkTelephone" name="AssignedEmergencyContacts_WorkTelephone[]"><span> </div> </div> <div id="dynamicinput" class="dynamicinput"> </div> 只做一个浅层克隆。 所以你有一个新的克隆外部数组,但它引用相同的条目(内部数组)。 克隆外部数组后,遍历外部数组并克隆所有内部数组以获得深度克隆。