作为一个对线性代数一无所知的开发者,想快速对向量和矩阵进行一个了解和认识,那么本文就正好适合你。
本文将站在开发者的角度的讲解向量和矩阵,并用TypeScript将其实现,欢迎各位感兴趣的开发者阅读本文。
向量是线性代数研究的基本元素,将一组数放在一起其基本的表示方法就是向量,例如:一个数: 100,一组数:(25,78,101)。其中一组数就可以称为向量,示例中的这组数是一个三维向量。
下述公式,描述了一个向量。
那么,一组数有什么用?
我们通过一个例子来说明,如下表所示:
序号 | 语文 | 数学 | 英语 |
---|---|---|---|
0 | 70 | 80 | 90 |
上述表格中,(0,70,80,90) 这组数分别描述了序号、语文、数学、英语,如果将这组数中数字的顺序调换顺序,那么其所表达的意思也就完全不同了,每个数字都代表着空间中的一个点,是一组有序的数字,因此他可以用来描述一个有序的东西。
标量:向量中的数字就称为标量。
向量中标量的个数,就是这个向量的维度。
例如,向量(3,4)
其维度就是2
接下来我们根据上面所述,先来看看我们都需要为向量实现哪些方法。
接下来,我们来一一实现这些方法。
Vector.ts
,用于实现向量的所有方法export class Vector {
constructor(private list: number[] = []) {}
}
getDimension
getDimension(): number {
return this.list.length;
}
length
len = this.getDimension();
getItem
/**
* 获取向量的特定元素
* @param index 目标元素索引
*/
getItem(index: number): number {
return this.list[index];
}
toStr(): string {
let str = ``;
for (let i = 0; i < this.list.length; i++) {
if (i !== this.list.length - 1) {
str += `${this.list[i]},`;
} else {
str += this.list[i];
}
}
return `Vector(${str})`;
}
向量有两种基本运算:即向量加法和向量数量乘法
如上所示,描述了两个向量相加,它的计算规则如下:
用一个向量和一个标量进行乘法运算,就称之为向量的数量乘法。
如上所示,描述了向量和标量相乘,它的计算规则如下:
两个向量相乘就称之为向量的点乘运算。
如上所示,描述了向量与向量相乘,它的计算规则如下:
上面我们讲解了向量的两个基本运算,接下来我们就可以根据这两个基本运算推导出更多的结论,我们将要实现的函数如下。
我们将上述函数一一实现
add
/**
* 向量的加法运算
* @param another 需要进行相加的向量
*/
add(another: Vector): Vector | string {
// 向量相加时,要确保其维度与当前维度相等
if (this.getDimension() === another.getDimension()) {
const finalList: number[] = [];
for (let i = 0; i < this.getDimension(); i++) {
finalList.push(this.getItem(i) + another.getItem(i));
}
return new Vector(finalList);
} else {
return "维度不相等,无法进行加法运算";
}
}
/**
* 向量的减法运算
* @param another
*/
sub(another: Vector): Vector | string {
// 与加法运算一样,维度必须相等
if (this.getDimension() === another.getDimension()) {
const finalList: number[] = [];
for (let i = 0; i < this.getDimension(); i++) {
finalList.push(this.getItem(i) - another.getItem(i));
}
return new Vector(finalList);
} else {
return "维度不相等,无法进行减法运算";
}
}
/**
* 向量的数量乘法运算
* @param K
*/
mul(K: number): Vector {
const finalList: number[] = [];
// 向量的乘法运算规则:用向量的每一个维度去和这个数相乘
for (let i = 0; i < this.getDimension(); i++) {
finalList.push(this.getItem(i) * K);
}
return new Vector(finalList);
}
division(K: number): Vector {
return this.mul(1 / K);
}
// 向量取正,即将向量中分量变成正数
pos(): Vector {
return this.mul(1);
}
// 向量取负,即将向量中分量变成负数
neg(): Vector {
return this.mul(-1);
}
dotMul(another: Vector): number | void {
if (another.getDimension() === this.getDimension()) {
let final = 0;
// 两个向量点乘的方法: 将每个向量中的元素互相进行乘法运算,将得到的结果相加
for (let i = 0; i < this.getDimension(); i++) {
final += this.getItem(i) * another.getItem(i);
}
return final;
} else {
console.log("两个向量点乘时其维度必须相等");
}
}
矩阵就是对向量的扩展,将一组向量放在一起就可以构建成一个矩阵,我们可以从两个角度去看待一个矩阵:行向量和列向量。
如上所示,描述了一个3*4
的矩阵,用数学公式表示为:A(m*n))
,其中m表示其行数,n表示其列数。
在上述矩阵中,a11
表示其在矩阵A的第1行第1列,a23
表示其在矩阵A的第2行的第3列,因此我们通常会用aij
来描述矩阵中的某个元素,i表示行,j表示列。
如果我们通过行向量的角度来看待这个矩阵的话,它就由3个向量组成。如果我们通过列向量的角度来看待这个矩阵的话,它就由4个向量组成。
我们来看看实现一个矩阵都要实现哪些方法:根据上述矩阵的描述,我们可以使用二维数组来描述矩阵。
接下来,我们将上述方法一一实现。
export class Matrix {
constructor(private twoDimArray: number[][]) {}
}
shape
/**
* 矩阵形状
* @returns [x,y] x行,y列
*/
shape(): number[] {
// 矩阵的长度就是矩阵的行数,矩阵中每个向量的维度就是其列数都相等,所以取其第0号元素的作为列数
return [this.twoDimArray.length, this.twoDimArray[0].length];
}
getRowNum
和列数getColNum
// 获取矩阵行数
getRowNum(): number {
return this.shape()[0];
}
// 获取矩阵列数
getColNum(): number {
return this.shape()[1];
}
size
size(): number {
const shape = this.shape();
return shape[0] * shape[1];
}
// 矩阵的长度,即:获取矩阵行数
len = this.getRowNum();
rowVector
rowVector(index: number): Vector {
return new Vector(this.twoDimArray[index]);
}
colVector
colVector(index: number): Vector {
// 存放指定列的元素
const finalList: number[] = [];
for (let i = 0; i < this.getRowNum(); i++) {
// 取出矩阵的每一行
const row = this.twoDimArray[i];
// 取出每一行中的指定列,将其存起来
finalList.push(row[index]);
}
// 返回向量
return new Vector(finalList);
}
getItem
getItem(position: number[]): number {
return this.twoDimArray[position[0]][position[1]];
}
矩阵的运算可分为:矩阵与矩阵相加、矩阵与标量相乘、矩阵与向量相乘、矩阵与矩阵相乘。
矩阵与矩阵相加就称为矩阵的加法运算。
上述公式描述了矩阵加法的运算过程,其运算方法如下:
矩阵与标量之间的乘法运算就称为矩阵数量乘法。
上述公式描述了矩阵与标量相乘的运算过程,其运算方法如下:
上述公式描述了矩阵与向量相乘的运算过程,其运算方法如下:
上述公式描述了矩阵与矩阵相乘的运算过程,其运算方法如下:
接下来,我们用代码将上述运算一一实现。
add
和减法运算sub
/**
* 加法运算
* @param another 另一个矩阵
* @return Matrix 新的矩阵
*/
add(another: Matrix): Matrix | void {
// 两个矩阵相加,其大小必须相等
if (this.size() === another.size()) {
const finalList: number[][] = [];
// 将矩阵的每个元素相加,构成新的矩阵
for (let i = 0; i < this.getRowNum(); i++) {
const row: number[] = [];
for (let j = 0; j < this.getColNum(); j++) {
// 相加每个元素
row.push(this.getItem([i, j]) + another.getItem([i, j]));
}
// 构建新的矩阵
finalList.push(row);
}
return new Matrix(finalList);
} else {
console.log("矩阵相加,其大小必须相等");
}
}
/**
* 减法运算
* @param another 另一个矩阵
* @return Matrix 新的矩阵
*/
sub(another: Matrix): Matrix | void {
// 两个矩阵相加,其大小必须相等
if (this.size() === another.size()) {
const finalList: number[][] = [];
// 将矩阵的每个元素相加,构成新的矩阵
for (let i = 0; i < this.getRowNum(); i++) {
const row: number[] = [];
for (let j = 0; j < this.getColNum(); j++) {
// 相加每个元素
row.push(this.getItem([i, j]) - another.getItem([i, j]));
}
// 构建新的矩阵
finalList.push(row);
}
return new Matrix(finalList);
} else {
console.log("矩阵相减,其大小必须相等");
}
}
mul
和除法运算division
/**
* 矩阵数量乘法
* @param K 目标值
* @return Matrix 新的矩阵
*/
mul(K: number): Matrix {
const finalList: number[][] = [];
// 运算规则: 用矩阵中每个向量的元素去乘以目标数量,返回新的矩阵
for (let i = 0; i < this.getRowNum(); i++) {
const row: number[] = [];
for (let j = 0; j < this.getColNum(); j++) {
row.push(this.getItem([i, j]) * K);
}
finalList.push(row);
}
// 构建新的矩阵并返回
return new Matrix(finalList);
}
/**
* 矩阵数量除法
* @param K 目标值
* @return Matrix 新的矩阵
*/
division(K: number): Matrix {
return this.mul(1 / K);
}
mulVector
/**
* 矩阵与向量相乘
* @param vector 进行乘法运算的的向量
* @return Vector 生成的新向量
*/
mulVector(vector: Vector): Vector | void {
// 矩阵与向量相乘时其列数必须等于向量的长度
if (vector.len === this.getColNum()) {
// 结果数组
const finalList: number[] = [];
// 计算规则:
// 1. 用矩阵的每一项的与向量的每一项做乘法运算
// 2. 将得到的结果累加
// 3. 将累加的结果放进结果数组中
// 4. 根据结果数组构建新的向量
for (let i = 0; i < this.getRowNum(); i++) {
// 当前矩阵的行向量与向量进行点运算
finalList.push(<number>this.rowVector(i).dotMul(vector));
}
// 遍历结束,根据结果生成向量,并将其返回
return new Vector(finalList);
} else {
console.log("矩阵与向量相乘时,矩阵的列数必须与向量的长度相等");
}
}
/**
* 矩阵与矩阵相乘
* @param matrix
*/
mulMatrix(matrix: Matrix): Matrix | void {
// 矩阵A的列数必须和矩阵P的行数相等
if (this.getColNum() === matrix.getRowNum()) {
// 存放最终结果的二维数组
const finalList = [];
// 拆分两个矩阵,将其拆分成向量与向量之间的点乘
for (let i = 0; i < this.getRowNum(); i++) {
// 存放结果行向量的数组
const resultList: number[] = [];
// 获取矩阵A的行向量
const rowVector = this.rowVector(i);
for (let j = 0; j < matrix.getColNum(); j++) {
// 获取矩阵P的列向量
const colVector = matrix.colVector(j);
// 将行向量与列向量进行点乘,将结果放进结果行向量数组中
resultList.push(<number>rowVector.dotMul(colVector));
}
// 将构建好的结果行向量放进最终结果的二维数组
finalList.push(resultList);
}
// 根据最终结果的二维数组构建矩阵
return new Matrix(finalList);
} else {
console.log("矩阵与矩阵相乘,其中一个矩阵的列数必须与另一个矩阵的行数相等");
}
}
本文用到的代码完整地址以及测试代码请移步GitHub仓库:
向量:Vector.ts & vectorTest.js
矩阵:Matrix.ts & MatrixTest.ts
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有