第 31 天: 整数矩阵及其运算
目标:
矩阵对象的创建.
getRows 等: getter, setter 在 java 里面很常用. 主要是为了访问控制.
整数矩阵的加法、乘法.
Exception 的抛出与捕获机制.
用 this 调用其它的构造方法以减少冗余代码.
代码看起来多, 但矩阵运算我们以前写过.
把数据类型修改成 double, 获得 DoubleMatrix.java, 以后会很有用.
getIdentityMatrix: 单位矩阵.
resultMatrix.data[i][i]: 成员变量的访问权限: 在同一类里面是可以直接使用的.
代码如下
import java.util.Arrays;
public class IntMatrix {
int[][] data;
public IntMatrix(int paraRows, int paraColumns) {
data = new int[paraRows][paraColumns];
}//the first constructor
public IntMatrix(int[][] paraMatrix) {
data = new int[paraMatrix.length][paraMatrix[0].length];
// 元素复制
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++) {
data[i][j] = paraMatrix[i][j];
} //j
} //i
}//the second constructor
public IntMatrix(IntMatrix paraMatrix) {
this(paraMatrix.getData());
}//third constructor
public static IntMatrix getIdentityMatrix(int paraRows) {
IntMatrix resultMatrix = new IntMatrix(paraRows, paraRows);
for (int i = 0; i < paraRows; i++) {
// According to access control, resultMatrix.data can be visited
// directly.
resultMatrix.data[i][i] = 1;
} //i
return resultMatrix;
}//getIdentityMatrix
public String toString() {
return Arrays.deepToString(data);
}//toString
public int[][] getData() {
return data;
}//getData
public int getRows() {
return data.length;
}//getRows
public int getColumns() {
return data[0].length;
}//getColumns
public void setValue(int paraRow, int paraColumn, int paraValue) {
data[paraRow][paraColumn] = paraValue;
}//setValue
public int getValue(int paraRow, int paraColumn) {
return data[paraRow][paraColumn];
}//getValue
public void add(IntMatrix paraMatrix) throws Exception {
// Step 1. 获取指定矩阵的值
int[][] tempData = paraMatrix.getData();
// Step 2. 确定矩阵规格大小
if (data.length != tempData.length) {
throw new Exception("Cannot add matrices. Rows not match: " + data.length + " vs. "
+ tempData.length + ".");
} //if
if (data[0].length != tempData[0].length) {
throw new Exception("Cannot add matrices. Rows not match: " + data[0].length + " vs. "
+ tempData[0].length + ".");
} //if
// Step 3. 求和
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++) {
data[i][j] += tempData[i][j];
} //j
} //i
}//add
public static IntMatrix add(IntMatrix paraMatrix1, IntMatrix paraMatrix2) throws Exception {
// Step 1. 克隆第一个矩阵
IntMatrix resultMatrix = new IntMatrix(paraMatrix1);
// Step 2.两矩阵求和
resultMatrix.add(paraMatrix2);
return resultMatrix;
}//add
public static IntMatrix multiply(IntMatrix paraMatrix1, IntMatrix paraMatrix2)
throws Exception {
// Step 1. 大小检验
int[][] tempData1 = paraMatrix1.getData();
int[][] tempData2 = paraMatrix2.getData();
if (tempData1[0].length != tempData2.length) {
throw new Exception("Cannot multiply matrices: " + tempData1[0].length + " vs. "
+ tempData2.length + ".");
} //if
// Step 2. 空间分配
int[][] resultData = new int[tempData1.length][tempData2[0].length];
// Step 3. 相乘
for (int i = 0; i < tempData1.length; i++) {
for (int j = 0; j < tempData2[0].length; j++) {
for (int k = 0; k < tempData1[0].length; k++) {
resultData[i][j] += tempData1[i][k] * tempData2[k][j];
} //k
} //j
} //i
// Step 4. 构造矩阵对象(这里不知道有什么意义)
IntMatrix resultMatrix = new IntMatrix(resultData);
return resultMatrix;
}//multiply
public static void main(String args[]) {
IntMatrix tempMatrix1 = new IntMatrix(3, 3);
tempMatrix1.setValue(0, 1, 1);
tempMatrix1.setValue(1, 0, 1);
tempMatrix1.setValue(1, 2, 1);
tempMatrix1.setValue(2, 1, 1);
System.out.println("The original matrix is: " + tempMatrix1);
IntMatrix tempMatrix2 = null;
try {
tempMatrix2 = IntMatrix.multiply(tempMatrix1, tempMatrix1);
} catch (Exception ee) {
System.out.println(ee);
} //try
System.out.println("The square matrix is: " + tempMatrix2);
IntMatrix tempMatrix3 = new IntMatrix(tempMatrix2);
try {
tempMatrix3.add(tempMatrix1);
} catch (Exception ee) {
System.out.println(ee);
} //try
System.out.println("The connectivity matrix is: " + tempMatrix3);
}//main
}
运行结果:
The original matrix is: [[0, 1, 0], [1, 0, 1], [0, 1, 0]]
The square matrix is: [[1, 0, 1], [0, 2, 0], [1, 0, 1]]
The connectivity matrix is: [[1, 1, 1], [1, 2, 1], [1, 1, 1]]
笔记:
在 Java 中通常采用 try catch 语句来捕获异常并处理。语法格式如下:
try {
逻辑代码块1;
} catch(ExceptionType e) {
处理代码块1;
}
在以上语法中,把可能引发异常的语句封装在 try 语句块中,用以捕获可能发生的异常。
如果 try 语句块中发生异常,那么一个相应的异常对象就会被拋出,然后 catch 语句就会依据所拋出异常对象的类型进行捕获,并处理。处理之后,程序会跳过 try 语句块中剩余的语句,转到 catch 语句块后面的第一条语句开始执行。
如果 try 语句块中没有异常发生,那么 try 块正常结束,后面的 catch 语句块被跳过,程序将从 catch 语句块后的第一条语句开始执行。
在以上语法的处理代码块1中,可以使用以下 3 个方法输出相应的异常信息。
printStackTrace() 方法:指出异常的类型、性质、栈层次及出现在程序中的位置。
getMessage() 方法:输出错误的性质。
toString() 方法:给出异常的类型与性质。
注意:catch 语句的参数类似于方法的声明,包括一个异常类型和一个异常对象。异常类型必须为 Throwable 类的子类,它指明 catch 语句可以处理的异常类型,异常对象则由运行时系统在 try 语句块中生成并被捕获。