矩阵减法混淆(Java)

时间:2016-01-15 01:42:02

标签: java arrays matrix

我差不多完成了一个添加,减去和缩放两个矩阵的程序。我为每个创建了两个测试用例,并在两个矩阵的大小不同,标准协议时添加了错误消息。但是,我遇到了第二个减法案例的问题。这是两个二维数组:

int[][] a = {{1,2},{3,4}};
int[][] b = {{2,3},{5,7}};

这里分别是减法方法,call和println:

public static int[][] subtraction(int[][] arr1, int[][] arr2){
        int rows1 = arr1.length;
        int rows2 = arr2.length;
        int columns1 = arr1[0].length;
        int columns2 = arr2[0].length;
        if (rows1 != rows2 || columns1 != columns2){
            System.out.print("Matrices are not the same size, please try again.");
            return null;
        }
        for (int i = 0; i < rows1; i++){
            for (int j = 0; j < columns1; j++){
                arr1[i][j] -= arr2[i][j];
            }
        }
        return arr1;
    }
System.out.println(Arrays.deepToString(subtraction(b, a)));
[[1, 1], [2, 3]]

退房吧?那么为什么呢......

System.out.println(Arrays.deepToString(subtraction(a, b)));

...打印这个?

[[1, 2], [3, 4]]

我已经做了很多挖掘数组文档和堆栈溢出,我从未见过这样的东西。程序只是打印第一个数组而不是完成计算。我在这里错过了什么吗?

感谢您理解我的困境。

3 个答案:

答案 0 :(得分:2)

这就是你想要的:

public class Matrix {

    public static void main(String[] args) {
        int[][] a = {{1,2},{3,4}};
        int[][] b = {{2,3},{5,7}};
        int [][] result = subtraction(b, a);
        System.out.println(toString(result));
        result = subtraction(a, b);
        System.out.println(toString(result));
    }

    private static String toString(int[][] result) {
        StringBuilder builder = new StringBuilder();
        builder.append("{");
        for (int i = 0; i < result[0].length; ++i) {
            builder.append("[");
            for (int j = 0; j < result[i].length; ++j) {
                builder.append(result[i][j]);
                if (j < result[i].length-1) {
                    builder.append(",");
                }
            }
            builder.append("]");
        }
        builder.append("}");
        return builder.toString();
    }

    public static int[][] subtraction(int[][] arr1, int[][] arr2){
        int rows1 = arr1.length;
        int rows2 = arr2.length;
        int columns1 = arr1[0].length;
        int columns2 = arr2[0].length;
        if (rows1 != rows2 || columns1 != columns2){
            System.out.print("Matrices are not the same size, please try again.");
            return null;
        }
        int [][] result = new int[rows1][columns1];
        for (int i = 0; i < rows1; i++){
            for (int j = 0; j < columns1; j++){
                result[i][j] = arr1[i][j] - arr2[i][j];
            }
        }
        return result;
    }
}

答案 1 :(得分:2)

我得到[[-1,-1],[ - 2,-3]],这是正确的,减法会改变第一个参数,所以运行

System.out.println(Arrays.deepToString(subtraction(b, a)));
System.out.println(Arrays.deepToString(subtraction(a, b)));

[[1,1],[2,3]] [[0,1],[1,1]]

所以也许您在调用减法(a,b)之前或之前已经改变了?

答案 2 :(得分:0)

您看到的问题是您的减法方法正在修改您传递它的Array对象(array1)中的值。当您再次调用该方法时,您现在正在传递数组的修改版本。您可以通过在减法方法内创建arr1参数的本地副本来解决此问题,如此

public static int[][] subtraction(int[][] arr1, int[][] arr2){
    int rows1 = arr1.length;
    int rows2 = arr2.length;
    int columns1 = arr1[0].length;
    int columns2 = arr2[0].length;
    if (rows1 != rows2 || columns1 != columns2){
        System.out.print("Matrices are not the same size, please try again.");
        return null;
    }
    // Create copies of the input parameter arrays to prevent modifying the origional
    int[][] copy1 = copyOf(arr1);
    for (int i = 0; i < rows1; i++){
        for (int j = 0; j < columns1; j++){
            copy1[i][j] -= arr2[i][j];
        }
    }
    return copy1;
}

public static int[][] copyOf(int[][] origional){
    int[][] copiedArray = new int[origional.length][origional[0].length];
    for(int i=0; i<origional.length; i++){
        for(int j=0; j<origional[i].length; j++){
            int x = origional[i][j];
            copiedArray[i][j] = x;
        }
    }
    return copiedArray;
}

在您的代码中,调用

System.out.println(Arrays.deepToString(subtraction(b, a)));
System.out.println(Arrays.deepToString(subtraction(a, b)));

相当于调用

System.out.println(Arrays.deepToString(subtraction({{2,3},{5,7}}, {{1,2},{3,4}})));
System.out.println(Arrays.deepToString(subtraction({{1,2},{3,4}}, {{1,1},{2,3}}))); // notice that the b array has been modified

当你假设它等同于调用

System.out.println(Arrays.deepToString(subtraction({{2,3},{5,7}}, {{1,2},{3,4}})));
System.out.println(Arrays.deepToString(subtraction({{1,2},{3,4}}, {{2,3},{5,7}}))); // here the b array has it's original values

为了更好地理解为什么会发生这种情况,请参阅以下摘录:

  

将对象变量传递给方法时,必须记住您传递的是对象引用,而不是实际的对象本身。请记住,引用变量包含一些位(表示底层VM)到达内存中特定对象(在堆上)的方式。更重要的是,您必须记住,您甚至没有传递实际的引用变量,而是传递引用变量的副本。变量的副本意味着您获得该变量中位的副本,因此当您传递引用变量时,您将传递表示如何到达特定对象的位的副本。换句话说,调用者和被调用的方法现在都具有相同的引用副本;因此,两者都将引用堆上相同的(非复制)对象。 Kathy Sierra&amp;伯特贝茨“OCA / OCP Java SE 7程序员I&amp; II学习指南(考试1Z0-803&amp; 1Z0-804)。