Работа с объектами в Java

Рейтинг: 0Ответов: 2Опубликовано: 28.02.2011

Помогите разобраться, почему в результате выполнения следующего кода получается нулевая матрица и как это исправить?

Класс для перемножения двух матриц:

public class Matrix {
    private static int[][] matrix;

    public Matrix(int rows, int cols) {
        if (rows < 1 || cols < 1) {
            throw new IllegalArgumentException("Dimensions must be greater than zero");
        }
        matrix = new int[rows][cols];
    }

    public void setElement(int row, int column, int value) {
        checkArgumentsIsLegal(row, column);
        matrix[row][column] = value;
    }

    public int getElement(int row, int column) {
        checkArgumentsIsLegal(row, column);
        return matrix[row][column];
    }

    public int getRowsNum() {
        return matrix.length;
    }
        // jkjnk
    public int getColumnsNum() {
        return matrix[0].length;
    }

    private void checkArgumentsIsLegal(int row, int column) {
        if (row < 0 || row >= getRowsNum()) {
            throw new IllegalArgumentException("Illegal row index");
        }

        if (column < 0 || column >= getColumnsNum()) {
            throw new IllegalArgumentException("Illegal column index");
        }
    }

    public Matrix multiply(Matrix multiplier) {
        int thisRows = getRowsNum();
        int thisCols = getColumnsNum();

        int otherRows = multiplier.getRowsNum();
        int otherCols = multiplier.getColumnsNum();
        int value = 0;
        if (thisCols != otherCols) {
            throw new IllegalArgumentException("...here could be your ad...");
        }
        Matrix result = new Matrix(thisRows, otherCols);

        for (int thisRow = 0; thisRow < thisRows; ++thisRow) {
            for (int otherCol = 0; otherCol < otherCols; ++otherCol) {

                for (int thisCol = 0; thisCol < thisCols; ++thisCol) {
                    for (int otherRow = 0; otherRow < otherRows; ++otherRow) {
                        value = matrix[thisRow][thisCol] * multiplier.getElement(otherRow, otherCol);
                    }
                }
                if ((value >>> 32) > 0) {
                    System.out.println("Integer overflow while multiplying matrixes.");
                }
                result.setElement(thisRow, otherCol, value);
            }
        }
        return result;
    }
}

Класс для ввода и вывода матриц:

public final class MatrixUtil {
    private MatrixUtil() {
    }

    public static Matrix fill(Matrix matrix) {
        for (int i = 0; i < matrix.getRowsNum(); ++i) {
            for (int j = 0; j < matrix.getColumnsNum(); ++j) {
                matrix.setElement(i, j, (int) (Math.random() * 10));
            }
        }
        return matrix;
    }

    public static void print(Matrix matrix) {
        int rows = matrix.getRowsNum();
        int cols = matrix.getColumnsNum();
        System.out.println("Matrix dimensions: [" + rows + "; " + cols + "]");
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                System.out.print(matrix.getElement(i, j) + " ");
            }
            System.out.println();
        }
    }
}

Класс с методом main():

public class MatrixRunner {
    /**
     * @param args
     * @throws IOException
     * @throws NumberFormatException
     */
    public static void main(String[] args) throws NumberFormatException, IOException {
        Matrix first = new Matrix(2, 3);

        MatrixUtil.fill(first);
        MatrixUtil.print(first);
        Matrix second = new Matrix(3, 4);
        MatrixUtil.fill(second);
        MatrixUtil.print(second);

        Matrix mul = first.multiply(first);
        MatrixUtil.print(mul);
    }
}

Ответы

▲ 2Принят

Ваш код однозначно не будет работать как минимум потому, что матрица у вас на самом деле всегда одна, поэтому делать несколько экземпляров класса Matrix не имеет смысла: данные матрицы - переменная matrix объявлена как статическая, так что перемножение матриц нельзя выполнить правильно.

Вот оно: вы в конструкторе создаёте новый экземпляр 2го массива. При создании матрицы для результата вы этим самым уничтожаете предыдущую матрицу. По умолчанию, данные в массиве обнулены, вот и в результирующей тоже нули. Во всех трёх будут нули... потому что массив один на всех.

Здесь явно ошибка:

value = matrix[thisRow][thisCol] * multiplier.getElement(otherRow, otherCol);

Вы выполняете перемножение в цикле.. а результат умножения выбрасываете в никуда, а в результирующую матрицу попадает только результат последнего перемножения.

(value >>> 32) > 0

И вы думаете, что это поможет вам обнаружить переполнение? В общем случае, это не сработает.

И наконец, что-то у вас подозрительно много вложений циклов в перемножении... вроде бы как вложенность должна быть тройная, а у вас четверная получилась.. во внутреннем цикле должно быть суммирование произведений.

▲ 1

Вот работающий код (для тех кому интересно).

Класс для перемножения двух матриц:

public class Matrix {
private final int[][] matrix;

public Matrix(int rows, int cols) {
    if (rows < 1 || cols < 1) {
        throw new IllegalArgumentException("Dimensions must be greater than zero");
    }
    matrix = new int[rows][cols];
}

public void setElement(int row, int column, int value) {
    checkArgumentsIsLegal(row, column);
    matrix[row][column] = value;
}

public int getElement(int row, int column) {
    checkArgumentsIsLegal(row, column);
    return matrix[row][column];
}

public int getRowsNum() {
    return matrix.length;
}

public int getColumnsNum() {
    return matrix[0].length;
}

private void checkArgumentsIsLegal(int row, int column) {
    if (row < 0 || row >= getRowsNum()) {
        throw new IllegalArgumentException("Illegal row index");
    }

    if (column < 0 || column >= getColumnsNum()) {
        throw new IllegalArgumentException("Illegal column index");
    }
}

public Matrix multiply(Matrix multiplier) {

    int thisRows = getRowsNum();
    int thisCols = getColumnsNum();

    int otherRows = multiplier.getRowsNum();
    int otherCols = multiplier.getColumnsNum();
    if (thisCols != otherRows) {
        throw new IllegalArgumentException("...here could be your ad...");
    }
    Matrix result = new Matrix(thisRows, otherCols);

    for (int thisRow = 0; thisRow < thisRows; ++thisRow)
        for (int otherCol = 0; otherCol < otherCols; ++otherCol)
            for (int thisCol = 0; thisCol < thisCols; ++thisCol) {
                result.matrix[thisRow][otherCol] += matrix[thisRow][thisCol]
                        * multiplier.getElement(thisCol, otherCol);
            }

    return result;
}

}

Класс для ввода и вывода матриц:

public final class MatrixUtil {

private MatrixUtil() {
}

public static Matrix fill(Matrix matrix) {
    for (int i = 0; i < matrix.getRowsNum(); ++i) {
        for (int j = 0; j < matrix.getColumnsNum(); ++j) {

            matrix.setElement(i, j, (int) (Math.random() * 10));
        }
    }
    return matrix;
}
public static void print(Matrix matrix) {
    int rows = matrix.getRowsNum();
    int cols = matrix.getColumnsNum();
    System.out.println("Matrix dimensions: [" + rows + "; " + cols + "]");
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            System.out.print(matrix.getElement(i, j) + " ");
        }
        System.out.println();
    }
}

}

Класс с методом main():

public class MatrixRunner {

/**
 * @param args
 * @throws IOException
 * @throws NumberFormatException
 */
public static void main(String[] args) throws NumberFormatException, IOException {

    Matrix first = new Matrix(1, 2);

    MatrixUtil.fill(first);
    MatrixUtil.print(first);
    Matrix second = new Matrix(2, 3);
    MatrixUtil.fill(second);
    MatrixUtil.print(second);

    Matrix mul = first.multiply(second);

    MatrixUtil.print(mul);

}

}