package L0613;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;
public class Rowmatrix {
// TODO Auto-generated method stub
public static double k = 1;
public long data[][];
public int row;
public int col;
public int rank;
// 构造函数,初始化调用
public Rowmatrix(int row, int col) {
// TODO Auto-generated constructor stub
this.row = row;
this.col = col;
data = new long[row][col];
// 初始化data数据
Random rand = new
Random(System.currentTimeMillis());
for(int i = 0; i < row; i ++) {
for(int j = 0; j < col; j++) {
data[i][j] = rand.nextInt(20);
//随机生成的数据在0~20之间
}
}
}
// 获取从Rowmatrix的第row行,col列的右下角子矩阵
public Rowmatrix getSubMatrix(int row, int col) {
Rowmatrix ans = new Rowmatrix(this.row - row,
this.col - col);
for(int i = row; i < this.row; i++)
System.arraycopy(data[i], col, ans.data[i -
row], 0, ans.col);
return ans;
}
// 将ans这个子矩阵覆盖到Rowmatrix的第row行,col列的右下角
// 需要满足ans.col+col != this.col;ans.row + row =this.row
public void setSubMatrix(int row, int col, Rowmatrix
ans) {
if(ans.col + col != this.col && ans.row + row !=
this.row) {
System.out.println("输入维度错误!");
return;
}
for(int i = row; i < this.row; i++)
System.arraycopy(ans.data[i - row], 0,
data[i], col, ans.col);
}
/** 显示数组,并保存到文件中
* 0 创建保存文件的位置
* 1 如果文件夹不存在,先创建
* 2 如果文件夹不存在,再创建
* 3 建立BufferedWriter类去向文件中写入数据
* 4 关闭BufferedWriter
* */
public void showAndSaveData(String des) throws
IOException {
System.out.printf("矩阵大小: %d * %d\n", row, col);
// 显示数组信息
for(int i = 0; i < row; i ++) {
for(int j = 0; j < col; j++) {
System.out.printf("%-10d", data[i][j]);
}
System.out.println();
}
File file = new File(des);
// 创建保存文件的位置
if(!file.getParentFile().exists()) {
// 如果文件夹不存在,先创建
file.getParentFile().mkdirs();
file.createNewFile();
}else if(!file.exists()) {
//2 如果文件夹不存在,再创建
file.createNewFile();
}
BufferedWriter bw = new BufferedWriter(new
FileWriter(file));
// 3 建立BufferedWriter类去向文件中写入数据
bw.write("行数:" + row + "\t列数:" + col + "\n");
bw.flush();
for(int i = 0; i < row; i ++) {
for(int j = 0; j < col; j++) {
bw.write(String.format("%-10d", data[i]
[j]));
}
bw.write("\n");
bw.flush();
}
bw.close();
// 4关闭BufferedWriter
}
// 将第row1行row2行互换
public void exchangeRow(int row1, int row2) {
//任意两行互换位置 这步操作会使矩阵的行列式变号
if(row1 != row2 ) Rowmatrix.k *= -1;
long[] temp = new long [col];
System.arraycopy(data[row1], 0, temp, 0, col);
System.arraycopy(data[row2], 0, data[row1], 0,
col);
System.arraycopy(temp, 0, data[row2], 0, col);
}
//将row1行数据乘以k加到row2行
public void multiAndAdd(int row1, int row2, int k) {
// 这个操作对某一行取相反数,所以会出现提取-1
if(row1 == row2 && k == -2) Rowmatrix.k *= -1;
for(int i = 0; i < col; i ++) {
data[row2][i] = data[row2][i] + data[row1][i]
* k;
}
}
/** 计算行矩阵
* 如果只有一行,则这个矩阵已经是行矩阵,不用计算
* 0 从上往下,从左往右定位到第一个不为0的数,并找到这个数所在列
的最小值所在行与第一行相交换。
* 1 将这一行数据×k然后依次加给剩下的行,其中k满足整数且必须使得
被加行的被定位到的列被加后最小且大于0
* 2 重复0 1步骤直到除第一行外被定位的列其他元素都为0
* 3 取出子矩阵,并计算子矩阵 0-1-2步骤,即利用迭代思想
* 4 将新的子矩阵覆盖在原矩阵中
* */
public void calcuMatrix() {
// 迭代退出出口
if(row <= 1) return;
while(true) {
// 2 重复0 1步骤直到除第一行外被定位的列其他元素都为0
// 0 从上往下,从左往右定位到第一个不为0的数,并找到这个数所在列的最小值所在行与第一行相交换。
int ex_row = 0, ex_col = 0;
boolean exit = false;
for(ex_col = 0; !exit && ex_col < col;
ex_col++)
// 从左往右
for(ex_row = 0; ex_row < row; ex_row++)
// 从上往下
if(data[ex_row][ex_col] != 0) {
exit = true;
ex_col--;
// 这是因为下一次for循环会使ex_col加1,为保持不变,提前减1
break;
}
// 全零也不用计算了
if(ex_row == row && ex_col == col) return;
int zeros_count = 0;
for(int i = ex_row + 1; i < row; i++) {
if(data[i][ex_col] == 0) zeros_count++;
}
if(ex_row == 0 && zeros_count == row - 1)
break;
// while 退出条件
// 定位ex_col列非零最小元素位置
for(int i = ex_row; i < row; i++) {
if(data[i][ex_col] < 0)
multiAndAdd(i, i, -2);
// 乘以-2就是取反得到相反数,保证都是正数
if(data[i][ex_col] < data[ex_row][ex_col]
&& data[i][ex_col] != 0) {
ex_row = i;
}
}
// 与第一行交换
exchangeRow(ex_row, 0);
// 1 将这一行数据×k然后依次加给剩下的行,其中k满足整数且必须使得被加行的被定位到的列被加后最小且大于0
for(int i = 1; i < row; i++) {
//求解这一行满足条件的k值
int idx = (int) (data[i][ex_col] / data[0]
[ex_col]);
// 利用强制类型转换,这样刚好得到相减的最小倍数
multiAndAdd(0, i, -idx);
}
}
// 取出子矩阵,并计算子矩阵 0-1-2步骤,即利用迭代思想
Rowmatrix temp = getSubMatrix(1, 0);
temp.calcuMatrix();
// 4 将新的子矩阵覆盖在原矩阵中
setSubMatrix(1, 0, temp);
}
/**
* 计算矩阵的秩
* 注意要先转换成行矩阵。调用calcuMatrix
*/
public void rank() {
rank = row;
for(int i = 0; i < row; i++) {
int zero = 0;
for(int j = 0; j < col; j++) {
if(data[i][j] == 0 ) zero++;
}
// 全为0 则秩减1
if(zero == col) rank--;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Rowmatrix matrix = new Rowmatrix(4, 5);
try {
matrix.showAndSaveData("data/rand.txt");
matrix.calcuMatrix();
matrix.showAndSaveData("data/ans.txt");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 计算矩阵的秩
matrix.rank();
System.out.println("矩阵的秩为" + matrix.rank);
// 计算行列式
long ans = 1;
if(matrix.row == matrix.col) {
for(int k = 0; k < matrix.row; k++) {
ans *= matrix.data[k][k];
}
ans *= Rowmatrix.k;
System.out.printf("矩阵的行列式为%d", ans);
}
}
}