程序猿成长之路之番外篇——矩阵算法

今天在复习线性代数知识的过程中,用java语言简单实现了一下矩阵算法。

数学知识回顾

1.什么是矩阵
在数学领域,矩阵就像一个表格,将数据排放进去,形成一个矩形。我们习惯用一个大括号把矩阵内的数据包括进来。

1.矩阵
在数学领域,矩阵就像一个表格,将数据排放进去,形成一个矩形。我们习惯用一个大括号把矩阵内的数据包括进来。

2. 矩阵的运算
矩阵可以进行加法、乘法运算,如果是个方形矩阵也可以转置或者求逆。此外,加法和乘法都有结合律、分配律等定律。

矩阵加法运算:
在这里插入图片描述
矩阵乘法运算:
运算规则相对较为繁琐:

  1. A(m,n) * B(n,k) = C(m,k) // 具有m行n列的矩阵A 乘以具有n行k列的矩阵B结果为m行k列的矩阵c
  2. 运算过程如下图:就拿C(1,1) – 结果矩阵的第一行第一列的元素来说,它等于A(1,1) * B(1,1) + A(1,2) * B(2,1) = 1 * 2 + 2 * 6 = 14
    在这里插入图片描述
  3. 矩阵的转置
    在这里插入图片描述
  4. 矩阵求逆
    我们知道伴随矩阵 = Det(矩阵A) * 矩阵的逆
    我们又知道 伴随矩阵 = Σ(Aij 的代数余子式), i,j∈(0,size))
    因此可以求出矩阵的逆 = |伴随矩阵| / Det(矩阵A)
    求逆的难点在于获取代数余子式。

算法实现

  1. 编写matrix类
package matrixUtils;import java.util.Arrays;class Matrix {@Overridepublic String toString() {String str = "";for (int i = 0; i < arr.length;i++) {str += Arrays.toString(arr[i]);str +="\n";}return str;}//宽度private final int width;//高度private final int height;//数组private final double[][] arr;Matrix(int width, int height) {this.width = width;this.height = height;arr = new double[height][width];}Matrix(int width, int height, double[][] arr) {this.width = width;this.height = height;this.arr = arr;}public int getWidth() {return width;}public int getHeight() {return height;}public double[][] getArr() {return arr;}public void setArrVal(int x, int y, double val) {arr[x][y] = val;}public boolean compareTo(Matrix matrix) {//比较return this.width == matrix.width & this.height == matrix.height;}public void setArrVals(int startIndex, int[][] val) {int size = val[0].length;size *= val.length;if (startIndex < 0 || size <= 0){return;}//count计数器for (int i = 0; i < size;i++) {arr[i / val[0].length][i % val[0].length] = val[i/val[0].length][i % val[0].length];}}}
  1. 编写工厂类
public class MatrixFactory {private static final int MAX_SIZE = 1 << 30;/*** 获取实例*/public static Matrix getInstance(int width, int height) {if (width < 0 || width > MAX_SIZE) {throw new IllegalArgumentException("宽度有误");}if (height < 0 || height > MAX_SIZE) {throw new IllegalArgumentException("高度有误");}return new Matrix(width, height);}public static Matrix getInstance(int width, int height, double[][] arr) {if (width < 0 || width > MAX_SIZE) {throw new IllegalArgumentException("宽度有误");}if (height < 0 || height > MAX_SIZE) {throw new IllegalArgumentException("高度有误");}return new Matrix(width, height, arr);}
}
  1. 矩阵乘法
    设计思路:设置一个计数器m,用于获取结果的列值,当m == matrix2的宽度时,也就是说当前已经完成对i行的处理,结果保存进matrix中,让i(行数)加1并且m重置为0,否则让结果列数自加。
	/*** 矩阵相乘* @param matrix* @return*/public static Matrix multiply(Matrix matrix1,Matrix matrix2) {//生成一个新的矩阵if (matrix1 == null || matrix2 == null) {throw new IllegalArgumentException("矩阵不匹配,请检查");}if (matrix1.getWidth() != matrix2.getHeight()) {throw new IllegalArgumentException("矩阵不匹配,请检查");}//新建一个矩阵Matrix resMatrix = MatrixFactory.getInstance(matrix2.getWidth(),matrix1.getHeight());int m = 0; //m - matrix2的列数for (int i = 0; i < matrix1.getHeight();) {int sum = 0; //sum - 求和for(int j = 0; j < matrix1.getWidth(); j++) {/*** 按照matrix1 第i行 * matrix2 第m列 得到结果保存*/sum += matrix1.getArr()[i][j] * matrix2.getArr()[j][m];}resMatrix.setArrVal(i, m, sum);if (m == matrix2.getWidth() - 1) {i++;m=0;} else {m++;}}return resMatrix;}
  1. 矩阵转置
    设计思路: arr[i][j] == arr[j][i]。(i,j位置上的数据互换)
/*** 矩阵反转* @param matrix* @return*/public static Matrix reverse(Matrix matrix) {//生成一个新的矩阵if (matrix == null) {throw new IllegalArgumentException("矩阵不匹配,请检查");}//生成一个新的矩阵Matrix resMatrix = MatrixFactory.getInstance(matrix.getHeight(), matrix.getWidth());for(int i =0; i <matrix.getHeight();i++) {for (int j = 0; j < matrix.getWidth(); j++) {//如果行列值一样就跳过if (i == j) {resMatrix.setArrVal(i, j, matrix.getArr()[i][j]);continue;}resMatrix.setArrVal(j, i, matrix.getArr()[i][j]);}}return resMatrix;}
  1. 矩阵求det
    设计思路:利用递归,每次的余子式size-1,到了size为2时就直接使用余子式公式进行计算。
/*** 获取矩阵det* @param matrix* @return*/public static double getMatrixDet(Matrix matrix) {if (matrix == null) {throw new IllegalArgumentException("矩阵不匹配,请检查");	}int height = matrix.getHeight();int width = matrix.getWidth();if (height != width) {throw new IllegalArgumentException("矩阵不匹配,请检查");	}return getMatrixDet(matrix,width);}/*** 获取矩阵det* @param matrix* @param width* @return*/private static double getMatrixDet(Matrix matrix, int size) {if (size <= 1) {return matrix.getArr()[0][0];} else if (size == 2) {return matrix.getArr()[0][0] * matrix.getArr()[1][1] - matrix.getArr()[0][1] * matrix.getArr()[1][0];}// 计算det,每次分解成大小为size-1的数组int det = 0;double[][] arr = matrix.getArr();for(int i = 0; i < arr[0].length; i++) {//获取余子式Matrix temp = getSubMatrix(0,i,size-1,arr);//统计det的值det += (Math.pow(-1, i)) * arr[0][i] * getMatrixDet(temp,size-1);}return det;}/*** 获取余子式* @param x - 要去除的第几行* @param y - 要去除的第几列* @param size 余子式size* @param arr 原数组* @return*/private static Matrix getSubMatrix(int x, int y,int size,double[][] arr) {//每次进行temp数组的填充Matrix temp = new Matrix(size,size);int addRow = 0; //填充计数for (int j = 0; j <= size; j++) {int addColumn = 0; //填充计数//跳过当前一行if (j == x) {addRow++;continue;}for (int m = 0; m < size + addColumn; m++) {//i列删除if (m == y) {addColumn++;continue;}//从第一行开始算,自动跳过第y列的数据temp.setArrVal(j-addRow,m - addColumn,arr[j][m]);}}return temp;}
  1. 矩阵求逆
    设计思路:利用公式 伴随矩阵 = det(矩阵) * 矩阵进行求解
/*** 求逆矩阵* @param matrix* @return*/public static Matrix inverse(Matrix matrix) {if (matrix.getWidth() != matrix.getHeight()) {throw new IllegalArgumentException("矩阵不匹配,请检查");}/*** AX = B* A-1AX=A-1A* X=A-1B*/int size = matrix.getHeight(); //sizedouble[][] arr = matrix.getArr(); //arr//结果矩阵Matrix resMatrix = MatrixFactory.getInstance(size,size);double det = getMatrixDet(matrix); //计算detfor (int i = 0; i < Math.pow(size,2); i++) { //size * size = length//获取每一项的余子式Matrix temp = getSubMatrix(i/size, i%size, size-1, arr);resMatrix.setArrVal(i/size, i%size, Math.pow(-1, i) * getMatrixDet(temp) / (det * 1.0)); //计算余子式的det / 总det}return reverse(resMatrix); //转置}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/763171.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript parseInt() 函数

JavaScript parseInt() 函数 从官方理解&#xff1a; parseInt() 函数解析字符串并返回整数。 radix 参数用于指定使用哪种数字系统&#xff0c;例如基数为 16&#xff08;十六进制&#xff09;表示字符串中的数字应从十六进制数解析为十进制数。 如果 radix 参数被省略&…

Java SE

java概述 1.什么是java java是一门面向对象的编程语言&#xff0c;作为静态面向对象编程语言&#xff0c;极好地实现了面向对象理论&#xff0c;允许程序员以优雅的思维方式进行复杂的编程 。 2.java语言有哪些特点&#xff1f; 2.1面向对象&#xff08;继承封装多多态&…

Uscrapper:一款功能强大的网络资源爬取工具

关于Uscrapper Uscrapper是一款功能强大的网络资源爬取工具&#xff0c;该工具可以帮助广大研究人员从各种网络资源中轻松高效地提取出有价值的数据&#xff0c;并且提供了稳定、友好且易于使用的UI界面&#xff0c;是安全研究人员和网络分析人员的强有力工具。 Uscrapper最大…

漫谈5种注册中心

01 注册中心基本概念 1.1 什么是注册中心&#xff1f; 注册中心主要有三种角色&#xff1a; 服务提供者&#xff08;RPC Server&#xff09;&#xff1a;在启动时&#xff0c;向 Registry 注册自身服务&#xff0c;并向 Registry 定期发送心跳汇报存活状态。 服务消费者&…

哈希、散列表和Rabin-Karp算法

字典 现有一个抽象数据类型(ADT)如下&#xff1a; 包括了一组元素&#xff0c;每个元素都有一个键key。假设没有元素拥有相同的key&#xff0c;如果有相同的key&#xff0c;则覆盖掉原有key的元素。 -insert(item) -delete(item) -search(key):根据给定的key&#xff0c;返…

JetBrains全家桶激活,分享 GoLand 2024 激活的方案

大家好&#xff0c;欢迎来到金榜探云手&#xff01; GoLand 公司简介 JetBrains 是一家专注于开发工具的软件公司&#xff0c;总部位于捷克。他们以提供强大的集成开发环境&#xff08;IDE&#xff09;而闻名&#xff0c;如 IntelliJ IDEA、PyCharm、和 GoLand等。这些工具被…

LVGL:拓展部件——键盘 lv_keyboard

一、概述 此控件特点&#xff1a; 特殊Button矩阵&#xff1a;lv_keyboard 本质上是一个经过定制的按钮矩阵控件。每个按钮都可以独立触发事件或响应。预定义的键映射&#xff1a;lv_keyboard 自带了一套预设的按键布局和对应的字符映射表&#xff0c;开发者可以根据需要选择…

此站点正在尝试打开 ,chrome/edge 允许http网站打开url schema

正常https链接会有首次允许选项 但http没有&#xff0c;每次都会弹出&#xff0c;非常烦人。 Chrome / Edge 配置 地址栏输入 chrome://flags/搜索Insecure origins treated as secure, 配置允许网站&#xff0c;需要协议和端口再次跳转会显示始终允许选项

关于5.x版本的Neo4j与py2neo的访问技巧

先说结果。 Neo4j是可以使用py2neo来操作的。而且网上搜到的教程和方法里&#xff0c;首推的http连接方法可能并不是最好的&#xff0c;应该用 bolt 方法可能更好。 对于大多数使用 py2neo 与 Neo4j 数据库进行交互的应用程序来说&#xff0c;建议使用 Bolt 协议&#xff08;即…

kafka面试篇

消息队列的作用&#xff1a;异步、削峰填谷、解耦 高可用&#xff0c;几乎所有相关的开源软件都支持&#xff0c;满足大多数的应用场景&#xff0c;尤其是大数据和流计算领域&#xff0c; kafka高效&#xff0c;可伸缩&#xff0c;消息持久化。支持分区、副本和容错。 对批处理…

C# 属性

C# 属性 访问器&#xff08;Accessors&#xff09; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks;namespace ConsoleApp2 {class Student{private str…

第十五届蓝桥杯模拟考试III_物联网设计与开发官方代码分析

目录 前言&#xff1a;显示界面部分&#xff1a;页面切换:数值的轮回调整&#xff1a;传递数据&#xff1a; 前言&#xff1a; 这次模拟的效果很不好。85分&#xff0c;4h的限时我花了两天完成&#xff0c;这个时间是远远超出要求的&#xff0c;而且最后还只拿到56分&#xff0…

基于electron29版本桌面应用app开发例子

基于electron29版本桌面应用app开发例子 htmljsnode.js 开发模式 生成package.json文件&#xff1a; yarn init --yes 或 npm init --yes 运行打包 yarn dev yarn build # electron与electron-builder版本不兼容问题处理办法&#xff1a; 在package.json中scripts中添加 “…

解决在 yolov8 训练自己的数据集时,matplotlib 中文乱码问题【woodwhales.cn】

为了更好的阅读体验&#xff0c;建议移步至笔者的博客阅读&#xff1a;解决在 yolov8 训练自己的数据集时&#xff0c;matplotlib 中文乱码问题 在 yolov8 训练自己的数据集时&#xff0c;如果 class 字典使用了中文&#xff0c;则在训练过程中会出现形如下面的警告&#xff1a…

力扣242. 有效的字母异位词

思路&#xff1a;字母相互抵消的思路&#xff0c;本题字符串中只包含小写字母26位&#xff0c;那就新建record数组int[26]&#xff0c;下标0-25&#xff0c;代表小写字母a-z, 需要通过 某字符减a 来达到这一目的&#xff1b; class Solution {public boolean isAnagram(String…

ginblog博客系统/golang+vue

ginblog博客系统 前台&#xff1a; 后台&#xff1a; Gitee的项目地址&#xff0c;点击进入下载 注意&#xff1a; 数据库文件导入在model里面&#xff0c;直接导入即可。 admin和front前后台系统记住修改https里的地址为自己的IP地址&#xff1a; front同上。

两数之和(python)

官方题目描述&#xff1a; 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现…

JSONP 实现跨域请求案例

后端使用 express 搭建&#xff0c;案例代码如下&#xff1a; const express require(express)const app express() const PORT 3000app.get(/data, (req, res) > {const jsonData {name: Alan,age: 666,city: GD}const callback req.query.callback // 获取前端中的回…

布隆过滤器原理介绍和典型应用案例

整理自己过去使用布隆过滤器的应用案例和理解 基本介绍 1970年由布隆提出的一种空间效率很高的概率型数据结构&#xff0c;它可以用于检索一个元素是否在一个集合中&#xff0c;由只存0或1的位数组和多个hash算法, 进行判断数据 【一定不存在或者可能存在的算法】 如果这些…

【机器学习300问】43、回归模型预测效果明明很好,为什么均方根误差很大?

一、案例描述 假设我们正在构建一个房地产价格预测模型&#xff0c;目标是预测某个城市各类住宅的售价。模型基于大量房屋的各种特征&#xff08;如面积、地段、房龄、楼层等&#xff09;进行训练。 回归模型在大部分情况下对于住宅价格预测非常精准&#xff0c;用户反…