Часто слышал про задачки, типо реализуйте класс для матриц, комплексных чисел и т.д. Вот, наконец-то, попробовал. Меня интересует мнение, хорошо ли он реализован? Может можно как-то по другому и куда собственно двигаться дальше? Можно ли как-то усложнить реализацию? И где можно найти задачи где нужно не только реализовывать алгоритмы (то есть сплошная математика), а еще и пользоваться возможностями языка (наследования, обобщения, обработка исключений и т.д.).
package matrix;
public class Matrix {
private final int rows;
private final int columns;
private int[][] matrix;
/****************** Constructors ******************/
public Matrix() {
this.rows = 1;
this.columns = 1;
this.matrix = new int[rows][columns];
}
public Matrix(int rows, int columns) throws MatrixException {
if(rows <= 0 || columns <= 0) {
throw new MatrixException("Заданы неверные размеры матрицы");
}
this.rows = rows;
this.columns = columns;
this.matrix = new int[rows][columns];
}
public Matrix(int size) throws MatrixException {
if(size <= 0) {
throw new MatrixException("Заданы неверные размеры матрицы");
}
this.rows = this.columns = size;
this.matrix = new int[size][size];
}
public Matrix(int[][] matrix) {
this.rows = matrix.length;
this.columns = matrix[0].length;
this.matrix = matrix;
}
/************************************************************************/
public static final Matrix sum(Matrix matrix1, Matrix matrix2) throws MatrixException {
if(!check(matrix1, matrix2, false)) {
throw new MatrixException("Размеры матриц не совпадают");
}
else {
int size;
if(!matrix1.checkSquare()) {
size = matrix1.rows > matrix1.columns ? matrix1.columns : matrix1.rows;
}
else {
size = matrix1.rows;
}
Matrix matrix = new Matrix(size);
for(int i = 0; i < matrix1.rows; i++) {
for(int j = 0; j < matrix1.columns; j++) {
matrix.matrix[i][j] = matrix1.matrix[i][j] + matrix2.matrix[i][j];
}
}
return matrix;
}
}
public static final Matrix multiply(Matrix matrix1, Matrix matrix2) throws MatrixException {
if(!check(matrix1, matrix2, true)) {
throw new MatrixException("Размеры матриц не совпадают");
}
else {
int size;
int n;
if(!matrix1.checkSquare()) {
size = matrix1.rows > matrix1.columns ? matrix1.columns : matrix1.rows;
n = matrix1.rows > matrix1.columns ? matrix1.rows : matrix1.columns;
}
else {
size = matrix1.rows;
n = matrix1.rows;
}
Matrix matrix = new Matrix(size);
matrix.fill(0);
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
for(int k = 0; k < n; k++) {
matrix.matrix[i][j] += matrix1.matrix[i][k]*matrix2.matrix[k][j];
}
}
}
return matrix;
}
}
public final void print() {
for(int i = 0; i < rows; i++) {
for(int j = 0; j < columns; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
}
public final void fill(int number) {
for(int i = 0; i < rows; i++) {
for(int j = 0; j < columns; j++) {
matrix[i][j] = 0;
}
}
}
private final static boolean check(Matrix matrix1, Matrix matrix2, boolean forMultiply) {
if(forMultiply) {
return ((matrix1.rows == matrix2.rows) && (matrix1.columns == matrix2.columns)) ||
(matrix1.columns == matrix2.rows);
}
else {
return (matrix1.rows == matrix2.rows) && (matrix1.columns == matrix2.columns);
}
}
public final boolean checkSquare() {
return rows == columns;
}
}
package matrix;
public class MatrixException extends Exception {
private String cause;
MatrixException(String cause) {
this.cause = cause;
}
public String cause() {
return this.cause;
}
}
В целом код мне понравился, вот несколько моментов, которые я бы переделал (это моё субъективное мнение, для краткости я не стал добавлять в каждое предложение слова "Мне кажется, что ..."):
Рассмотрим метод check
. Он принимает два параметра и булевый флаг, и в зависимости от флага выполняет два разных кода. Что если вы добавите к операциям сложения и умножения третью операцию? Как тогда будет определяться, какую из трёх проверок делать (не передавать же два флага)? Лучше разделить этот метод на два, checkSum
и checkMultiply
. Ещё лучше убрать эти методы (они всё равно используются только в методах sum
и multiply
) и занести код проверок внутрь методов sum
и multiply
, так код станет понятней.
Рассмотрим фрагмент кода в методе sum
:
int size;
if (!matrix1.checkSquare()) {
size = matrix1.rows > matrix1.columns ? matrix1.columns : matrix1.rows;
} else {
size = matrix1.rows;
}
начнём с этой строчки:
size = matrix1.rows > matrix1.columns ? matrix1.columns : matrix1.rows;
тут берётся минимум из matrix1.columns
и matrix1.rows
. Если переписать через Math.min
, получится лучше:
if (!matrix1.checkSquare()) {
size = Math.min(matrix1.rows, matrix1.columns);
} else {
size = matrix1.rows;
}
далее, подумаем, нужен ли нам вообще if
? Если матрица квадратная, то matrix1.rows == matrix1.columns
и вариант кода для неквадратной матрицы корректно обработает этот случай. Таким образом фрагмент можно сократить до
int size = Math.min(matrix1.rows, matrix1.columns);
Далее, зачем нам вообще в методе sum
было вычислять минимум из размерностей матриц? Если матрицы неквадратные, то где-то дальше по коду возникнет исключение ArrayIndexOutOfBoundsException
. Возможно вместо минимума должен вычисляться максимум, но это тоже не очень хорошо: почему суммой двух матриц должна обязательно быть квадратная матрица? ЛУчше если суммой двух матриц будет матрица такой же размерности. Поэтому я бы переписал метод вот так:
public static final Matrix sum(Matrix matrix1, Matrix matrix2) throws MatrixException {
if (matrix1.rows != matrix2.rows || matrix1.columns != matrix2.columns) {
throw new MatrixException("Размеры матриц не совпадают");
} else {
Matrix matrix = new Matrix(matrix1.rows, matrix1.columns);
for(int i = 0; i < matrix1.rows; i++) {
for(int j = 0; j < matrix1.columns; j++) {
matrix.matrix[i][j] = matrix1.matrix[i][j] + matrix2.matrix[i][j];
}
}
return matrix;
}
}
Метод multiply
также всегда возвращает квадратную матрицу, стоит исправить, чтобы для матриц размера n x m
и m x k
возвращал матрицу n x k
.
Рассмотрим метод fill(int number)
:
public final void fill(int number) {
for(int i = 0; i < rows; i++) {
for(int j = 0; j < columns; j++) {
matrix[i][j] = 0;
}
}
}
здесь небольшая опечатка, вместо заполнения матрицы числом number
происходит заполнение матрицы нулями.
Метод checkSquare
лучше назвать isSquare
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Есть таблица в xhtml файле на JFSТребуется, при помощи JQuery проверить значения в ячейках конкретного столбца и при совпадении с образцом изменить...