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

今天在复习线性代数知识的过程中,用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.rhkb.cn/news/282355.html

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

相关文章

Linux系统部署DolphinScheduler任务调度系统并实现无公网IP远程访问

文章目录 前言1. 安装部署DolphinScheduler1.1 启动服务 2. 登录DolphinScheduler界面3. 安装内网穿透工具4. 配置Dolphin Scheduler公网地址5. 固定DolphinScheduler公网地址 前言 本篇教程和大家分享一下DolphinScheduler的安装部署及如何实现公网远程访问&#xff0c;结合内…

黑马现有java课程框架及其功能梳理

目录 高并发相关提高通信效率Netty作用&#xff1a;哪些框架使用它&#xff1a; ChannelChannelHandler 和 ChannelPipelineEventLoop 和 EventLoopGroup**涉及的名词解释&#xff1a;**NIOSocketNginx 高并发相关 主要用来解决IO密集型程序&#xff08;大量文件读写&#xff…

python矢量算法-三角形变化寻找对应点

1.算法需求描述 现有随机生成的两个三角形A与B&#xff0c;在三角形A中存在Pa&#xff0c;使用算法计算出三角形B中对应的点Pb 2.python代码 import numpy as np # 计算三角形A的面积 def area_triangle(vertices): return 0.5 * np.abs(np.dot(vertices[0] - vertices[…

大数据架构设计

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/136657478 一. 基本概念 1、解决传统数据架构无法及时响应用户请求的常用解决方法&#xff1a; ● 增加异步处理队列&#xff0c;通过工作处理层批量处理异步处理队列中的数据修改请求。 ● 建立数据库…

策略分析是什么?一文说清策略分析的方方面面!附10款策略分析必备模板!

在日益激烈的商业竞争环境中&#xff0c;有效的策略分析不仅能帮助企业全面了解自身的优势与劣势&#xff0c;同时也能提供决策制定的关键依据。一个优质的策略分析报告能帮助企业从宏观与微观两个层面洞察市场动态&#xff0c;掌握竞争对手信息&#xff0c;以及制定未来的战略…

C语言复杂度(个人笔记)

时间复杂度主要衡量一个算法的运行快慢. 空间复杂度主要衡量一个算法运行所需要的额外空间. 时间复杂度 算法中的基本操作的执行次数&#xff0c;为算法的时间复杂度. 只需要大概执行次数&#xff0c;我们使用大O的渐进表示法。(看谁对数学表达式的影响最大) 空间复杂度 是…

2.Redis有五种主要的数据类型

Redis有五种主要的数据类型 String&#xff08;字符串&#xff09;&#xff1a;String类型是最简单的数据类型&#xff0c;可以存储任意类型的数据&#xff0c;例如整数、浮点数、字符串等。String类型支持一些基本的操作&#xff0c;如设置值、获取值、增减值等。 Hash&#…

杂记8---多线激光雷达与相机外参标定

背景&#xff1a;本人开源的标定程序&#xff0c;提供大家参考学习 基于棋盘格的多线激光雷达和鱼眼/针孔模型相机外参标定的程序 前言 标定数据&#xff0c;只需要一个棋盘格标定板。把标定板放置lidar 与camera 共视区域&#xff0c;拜拍几个pose进行采集。 基于简谐原则…

webpack5零基础入门-12搭建开发服务器

1.目的 每次写完代码都需要手动输入指令才能编译代码&#xff0c;太麻烦了&#xff0c;我们希望一切自动化 2.安装相关包 npm install --save-dev webpack-dev-server 3.添加配置 在webpack.config.js中添加devServer相关配置 /**开发服务器 */devServer: {host: localhos…

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

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

内容检索(2024.03.22)

随着创作数量的增加&#xff0c;博客文章所涉及的内容越来越庞杂&#xff0c;为了更为方便地阅读&#xff0c;后续更新发布的文章将陆续在此汇总并附上原文链接&#xff0c;感兴趣的小伙伴们可持续关注文章发布动态&#xff01; 本期更新内容&#xff1a; 1. 真实案例分享--E…

C#,人工智能,机器学习,聚类算法,训练数据集生成算法、软件与源代码

摘要:本文简述了人工智能的重要分支——机器学习的核心算法之一——聚类算法,并用C#实现了一套完全交互式的、可由用户自由发挥的,适用于聚类算法的训练数据集生成软件——Clustering。用户使用鼠标左键(拖动)即可生成任意形状,任意维度,任意簇数及各种数据范围的训练数…

【python】flask请求钩子,主动抛出异常与异常捕获

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

综合实验---Web---进阶版

目录 实验配置&#xff1a; 1.PHP调整主配置文件时&#xff0c;修改文件内容 1.原内容调整(在编译安装的情况下) 2.调整如下 3.没有调整的&#xff0c;根据之前配置就行 2.配置Nginx支持PHP解析 1.原内容如下 2.调整如下 3.验证PHP测试页 1.原内容如下 2.调整如下 4…

Vant4:自动导入样式无效问题

今天前端小伙伴使用了Vant4&#xff0c;发现了一个奇怪的问题&#xff1a;按照Vant官方文档&#xff0c;按需引入组件样式&#xff08;Vite 的项目&#xff09;&#xff1a; 安装插件 # 通过 npm 安装 npm i vant/auto-import-resolver unplugin-vue-components unplugin-aut…

Linux——du, df命令查看磁盘空间使用情况

一、实现原理&#xff1a; df 命令的全称是Disk Free &#xff0c;显而易见它是统计磁盘中空闲的空间&#xff0c;也即空闲的磁盘块数。它是通过文件系统磁盘块分配图进行计算出的。 du 命令的全称是 Disk Used &#xff0c;统计磁盘有已经使用的空间。它是直接统计各文件各目…

金融知识分享系列之:支撑阻力

金融知识分享系列之&#xff1a;支撑阻力 一、支撑阻力原理二、支撑阻力作用1.识别市场资金的预期2.作为入场和平仓的重要参考 三、寻找支撑阻力四、延伸思考五、支撑阻力总结 一、支撑阻力原理 支撑阻力核心要素&#xff1a; 锚定效应订单驱动 支撑阻力原理&#xff1a; 市…

产品经理面试如何自我介绍?

金三银四求职季&#xff0c;你是不是也有面试的冲动&#xff01;但面试并不是头脑一热就能取得好结果&#xff0c;在此之前&#xff0c;必须得有周全的准备&#xff0c;才能应对好面试官的“连环问”&#xff01; 所以&#xff0c;今天这篇产品经理面试干货文章&#xff0c;别…

数据结构--链表刷题(一)快慢指针

1.快慢指针 先看一道简单的题目&#xff1a;返回中间结点 这道题有一个最朴素的做法就是先遍历一边链表&#xff0c;设置计数器求出链表长度&#xff0c;再重新走1/2的链表长度&#xff0c;即可返回中间节点 // 第二种解法 //这种解法需要遍历两次链表ListNode cur1 head;int…

Git基础(24):分支回退

前言 将分支回退到之前的某个版本 开发中&#xff0c;可能开发某个功能不需要了&#xff0c;或者想要回退到之前历史的某个commit&#xff0c; 放弃后来修改的内容。 放弃已修改的内容 如果未提交&#xff0c;直接使用 git revert分支回退到指定commit 操作前的分支网络图…