我被安排使用文件输入执行矩阵乘法的任务。乘法过程的实际数学运算没有问题;将数据存储到二维数组中使我感到困惑。
这是我用来创建二维数组的数据文件:
matrix
row
1
2
-2
0
row
-3
4
7
2
row
6
0
3
1
matrix
row
-1
3
row
0
9
row
1
-11
row
4
-5
规则很简单:新矩阵的开始将以“矩阵”表示,新行的开始将以“行”表示,后跟分配给该行每一列的数字。>
对于上下文,这是我的矩阵乘法方法:
static int[][] mult(int[][] a, int[][] b) {
int aRow = a.length;
int aCol = a[0].length;
int bRow = b.length;
int bCol = b[0].length;
if (bRow != aCol) {
throw new IllegalArgumentException("Matrix A is not multipliable by Matrix B");
}
int[][] product = new int[aRow][bCol];
for (int i = 0; i < product.length; i++) {
for (int j = 0; j < product[i].length; j++) {
for (int k = 0; k < aCol; k++) {
product[i][j] += a[i][k] * b[k][j];
}
}
}
return product;
}
这是具有main方法的类,在该类中,我尝试将上述文本文件中的数据存储到二维数组中(尝试将第一个矩阵存储到名为“ a”的2d数组中,将第二个矩阵存储到名为“ b”的二维数组):
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("/Users/Krish/IdeaProjects/Lessons/src/Lesson34/MatrixData.txt"));
String text[] = new String[100];
int index = -1;
while (scanner.hasNext()) {
text[++index] = scanner.nextLine();
}
int[][] a = {{}};
int[][] b = {{}};
int[][] product = MatrixMult.mult(a, b);
for (int i = 0; i < product.length; i++) {
for (int j = 0; j < product[i].length; j++) {
System.out.print(product[i][j] + "\t");
}
System.out.println();
}
scanner.close();
}
我知道我必须执行以下操作,但是说实话,我不知道如何做,并且非常感谢您的帮助/指导:
for (int i = 0; i <= index; i++) {
Scanner line = new Scanner(text[i]);
int n = 0;
while (line.hasNextInt()) {
n = line.nextInt();
for (int j = 0; j < a.length; j++) {
for (int k = 0; k < a[j].length; k++) {
a[j][k] = n;
}
}
}
}
答案 0 :(得分:2)
我建议您使用Java集合而不是数组,并以这种方式读取矩阵。 例如,您从输入流中读取“矩阵”值并调用此方法:
private int[][] readMatrix(final BufferedReader reader) {
List<List<Integer>> matrix = new ArrayList<>();
int rowNumber = -1;
while(reader.hasNext()) {
String value = reader.readLine();
if ("row".equals(value)) {
++rowNumber;
matrix.add(new ArrayList<Integer>());
} else {
int intValue = Integer.parseInt(value);
matrix.get(rowNumber).add(intValue);
}
}
// convert to an array
int[][] array = new int[matrix.size()][];
for (int i = 0; i < matrix.size(); ++i) {
List<Integer> row = matrix.get(i);
array[i] = row.toArray(new int[row.size()]);
}
return array;
}
答案 1 :(得分:0)
这应该可以解决问题(使用静态数组实现):
public class Main {
private static final String MATRIX_WORD = "matrix";
private static final String ROW_WORD = "row";
public static void main(String[] args) throws FileNotFoundException {
int[][][] allMatrix = getAllMatrix(args[0]);
for (int[][] currentMatrix : allMatrix) {
for (int i = 0 ; i < currentMatrix.length; i++) {
for (int j = 0; j < currentMatrix[i].length; j++) {
System.out.print(currentMatrix[i][j] + " ");
}
System.out.println();
}
System.out.println("\n\n");
}
}
private static int[][][] getAllMatrix(String fileName) throws FileNotFoundException {
int[][][] allMatrix = new int[0][0][0];
int[][] currentMatrix = new int[0][0];
String line;
try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
while ((line = br.readLine()) != null) {
switch (line) {
case MATRIX_WORD:
allMatrix = Arrays.copyOf(allMatrix, allMatrix.length + 1);
allMatrix[allMatrix.length - 1] = currentMatrix;
currentMatrix = new int[0][0];
break;
case ROW_WORD:
currentMatrix = Arrays.copyOf(currentMatrix, currentMatrix.length + 1);
currentMatrix[currentMatrix.length - 1] = new int[0];
break;
default:
currentMatrix[currentMatrix.length - 1] = Arrays.copyOf(currentMatrix[currentMatrix.length - 1],
currentMatrix[currentMatrix.length - 1].length + 1);
currentMatrix[currentMatrix.length - 1][currentMatrix[currentMatrix.length - 1].length - 1] = Integer.parseInt(line);
break;
}
}
allMatrix = Arrays.copyOf(allMatrix, allMatrix.length + 1);
allMatrix[allMatrix.length - 1] = currentMatrix;
} catch (IOException e) {
e.printStackTrace();
}
return allMatrix;
}
}
我使用Arrays.copyof()
扩展了当前数组(让它为元素留出更多空间)。
对于您的输入文件,输出为:
1 2 -2 0
-3 4 7 2
6 0 3 1
-1 3
0 9
1 -11
4 -5
我确定该算法仍有改进的空间,但是应该给出正确的结果。
答案 2 :(得分:0)
public static void main(String[] args) throws FileNotFoundException {
/*
* -3 43
* 18 -60
* 1 -20
*/
Scanner scanner = new Scanner(new File("/Users/Krish/IdeaProjects/Lessons/src/Lesson34/MatrixData"));
String[] text = new String[100];
int index = -1;
while (scanner.hasNext()) {
text[++index] = scanner.nextLine();
}
scanner.close();
int matrixCount = 0;
int rowCount = 0, colCount = 0;
int aRows = 0, aCols = 0;
int bRows, bCols;
for (int i = 0; i <= index; i++) {
switch (text[i]) {
case "matrix":
if (++matrixCount == 2) {
aRows = rowCount;
aCols = colCount;
}
rowCount = 0;
colCount = 0;
break;
case "row":
rowCount++;
colCount = 0;
break;
default:
colCount++;
break;
}
}
bRows = rowCount;
bCols = colCount;
int[][] a = new int[aRows][aCols];
int[][] b = new int[bRows][bCols];
matrixCount = 0;
int rowIndex = -1, colIndex = -1;
for (int i = 0; i <= index; i++) {
switch (text[i]) {
case "matrix":
matrixCount++;
rowIndex = -1;
colIndex = -1;
break;
case "row":
rowIndex++;
colIndex = -1;
break;
default:
colIndex++;
if (matrixCount == 1) {
a[rowIndex][colIndex] = Integer.parseInt(text[i]);
} else {
b[rowIndex][colIndex] = Integer.parseInt(text[i]);
}
break;
}
}
int[][] product = MatrixMult.mult(a, b);
for (int i = 0; i < product.length; i++) {
for (int j = 0; j < product[i].length; j++) {
System.out.print(product[i][j] + "\t");
}
System.out.println();
}
}
答案 3 :(得分:0)
我建议不使用for循环和完整输入验证的解决方案。 代替循环,可以使用Java 8流 验证阶段包括:正则表达式匹配,尺寸和尺寸检查。
The solution includes the following steps:
- Reading input matrices.
- Validating matrices.
- Converting the input into 3-d int array, with 2 cells.
(Each cell contains a 2-d int array matrix)
- Multiplying the matrices.
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.stream.IntStream;
import org.apache.commons.io.FileUtils;
/**
* This class demonstrates multiplication of 2 matrices.
* Including:
* - Reading input matrices from file.
* - Validating matrices input format (using Regex).
* - Converting input to 3-d array with 2 matrices (using streams).
* - Validating matrices sizes & dimensions.
* - multiplication of matrices (using streams).
*/
public class CreateTwo2dArraysFromATextFile {
final private static String FILE_PATH = "matrices.txt";
final private static String ENCODING = "UTF-8";
final private static String INPUT_FORMAT = "^(-?\\s*matrix\\s*(-?\\s+row(\\s+-?(\\d+))+)+){2}$";
final private static String MATRIX_TITLE = "matrix";
final private static String ROW_TITLE = "row";
final private static String MATRIX_DELIMITER = "\r\n";
final private static String ROW_DELIMITER = "\r\n";
public static void main(String[] args) throws IOException {
int[][][] matrices = fetchMatrices();
validateMatrices(matrices[0], matrices[1]);
displayMatrices(matrices);
displayMatricesMultiplicationResult(matrices[0], matrices[1]);
}
/**
* - Read 2 matrices from input file
* - Validate input format
* - Extract 2 matrices from the input file
* @return 2 matrices in 3-d int array format
* @throws IOException
*/
private static int[][][] fetchMatrices() throws IOException{
String input = FileUtils.readFileToString(new File(getFile(FILE_PATH)), ENCODING);
validateInputFormat(input);
System.out.println("Input from " + FILE_PATH);
System.out.println(input);
return getMatrices(input);
}
private static void validateMatrices(int[][] m1, int[][] m2) {
StringBuilder errors = collectInputErrors(m1, m2);
if(errors != null) {
throw new RuntimeException(errors.append("\nCannot multiply matrices, becuase the input is invalid").toString());
}
}
private static void displayMatrices(int[][][] matrices) {
System.out.println("\nMatrices in 3-d int array format:");
System.out.println(Arrays.deepToString(matrices));
}
private static void displayMatricesMultiplicationResult(int[][] m1, int[][] m2) {
System.out.println("\nMatrices Multiplication result:");
int[][] multResult = multiplyMatrices(m1, m2);
System.out.println(Arrays.deepToString(multResult));
}
private static String getFile(String fileName){
return Thread.currentThread().getContextClassLoader().getResource(fileName).getPath();
}
private static boolean isValidInput(String input) {
return input != null && input.matches(INPUT_FORMAT);
}
private static void validateInputFormat(String input) {
if(!isValidInput(input)) {
throw new RuntimeException("Invalid input format: " + input);
}
}
/**
* Attempt to detect the following validation errors:
* - The number of columns in m1 or m2 is not identical across all of the rows
* (There is at least one row with number of columns, which is different than the number of columns of all of the rows)
* - Matrices multiplication size constraints: the number of columns in m1, must be equals to the number of rows in m2.
* @param m1 first matrix
* @param m2 second matrix
* @return error messages if validation violations are detected.
* Otherwise, null will be retrieved.
*/
private static StringBuilder collectInputErrors(int[][] m1, int[][] m2) {
StringBuilder errors = new StringBuilder();
int invalidSizeRowIndex1 = getInValidSizeMatrixRowIndex(m1);
int invalidSizeRowIndex2 = getInValidSizeMatrixRowIndex(m2);
if(invalidSizeRowIndex1 != -1 || invalidSizeRowIndex2 != -1) {
errors.append("Invalid matrices size detected:");
}
if(invalidSizeRowIndex1 != -1) {
errors.append(getInvalidMatrixMessage(
"first",invalidSizeRowIndex1 + 1,
m1[invalidSizeRowIndex1].length, m1[invalidSizeRowIndex1 - 1].length));
}
if(invalidSizeRowIndex2 != -1) {
errors.append(getInvalidMatrixMessage(
"second",invalidSizeRowIndex2 + 1,
m2[invalidSizeRowIndex2].length, m2[invalidSizeRowIndex2 - 1].length));
}
int invalidDimensionRowIndex = getDimensionViolationIndex(m1, m2);
if(invalidSizeRowIndex1 == -1 && invalidSizeRowIndex2 == -1 && invalidDimensionRowIndex == -1) {
return null;
}
if(invalidDimensionRowIndex != -1 ) {
errors.append("\nInvalid matrices dimensions detected:");
errors.append(getInvalidMatrixMessage(
"first",invalidDimensionRowIndex + 1,
m1[invalidDimensionRowIndex].length, m2.length));
}
return errors;
}
private static String getInvalidMatrixMessage(String matrixTitle, int invalidRowIndex, int columnSize, int expectedColumnSize) {
return String.format("In the %s matrix, at the %d 'th row, a column with size of %d , is invalid. (expected column size is: %d)",
matrixTitle, invalidRowIndex, columnSize, expectedColumnSize);
}
/**
* Get the index of the first row in m1, that violates the matrices multiplication size constraints
* Matrix multiplication is possible iff the number of columns in m1 equals to the number of rows in m2.
* @param m1 first matrix
* @param m2 second matrix
* @return the first row index in m1 with column size
* which is different than the number of rows in m2.
* If there is no such row, then (-1) will be retrieved.
*
*/
private static int getDimensionViolationIndex(int[][] m1, int[][] m2) {
return IntStream.range(0, m1.length).filter(i -> m1[i].length != m2.length).findFirst().orElse(-1);
}
/**
* Get the index of the first row with invalid columns size (If exist)
* @param m matrix
* @return the first index of row,
* which has number of columns that is different than the previous row.
* If there is no such row, then (-1) will be retrieved.
*/
private static int getInValidSizeMatrixRowIndex(int[][] m) {
return IntStream.range(1, m.length).filter(i -> m[i].length != m[i-1].length).findFirst().orElse(-1);
}
/**
* Extract 2 matrices in 3-d int array format, using streams
* @param input
* @return 3-d int array,
* where the first cell is the first 2-d matrix
* and the second cell is the second 2-d matrix
*/
private static int[][][] getMatrices(String input) {
return Arrays.asList(input.split(MATRIX_TITLE))
.stream().filter(e -> !e.equals(""))
.map(k-> Arrays.stream(k.split(MATRIX_TITLE))
.map(r -> r.split(MATRIX_DELIMITER + ROW_TITLE))
.flatMap(r -> Arrays.stream(r))
.filter(e -> !e.equals(""))
.map(r-> Arrays.stream(r.split(ROW_DELIMITER))
.filter(e -> !e.equals(""))
.mapToInt(Integer::parseInt).toArray()
).toArray(int[][]::new)).toArray(int[][][]::new);
}
/**
* Multiply 2 matrices
* @param m1 first matrix
* @param m2 second matrix
* @return m1 X m2
*/
private static int[][] multiplyMatrices(int[][] m1, int[][] m2) {
return Arrays.stream(m1).map(r ->
IntStream.range(0, m2[0].length).map(i ->
IntStream.range(0, m2.length).map(j -> r[j] * m2[j][i]).sum()
).toArray()).toArray(int[][]::new);
}
}
注意:如果您想更改输入格式。例如定界符,您可以更改相关常量:
例如,以这种格式输入的内容: 矩阵行-2 0 1 3行-3 5 1 2行0 4 3 1矩阵行-1 3 4行0 4 9行1 -11 5行4 -5 7 使用此配置: MATRIX_DELIMITER =“” ROW_DELIMITER =“”
对于给定的输入,是分隔的行(例如您的示例中描述的输入) 使用此配置: MATRIX_DELIMITER =“ \ r \ n” ROW_DELIMITER =“ \ r \ n”