1 Star 0 Fork 63

caoweilin / goNum

forked from 黑影 / goNum 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
Matrix.go 7.54 KB
一键复制 编辑 原始数据 按行查看 历史
黑影 提交于 2019-03-01 10:10 . update comments
// Matrix
/*
------------------------------------------------------
作者 : Black Ghost
日期 : 2018-11-20
版本 : 0.0.0
0.0.1 2018-12-11 增加切片与矩阵转换
0.0.2 2018-12-26 增加错误报告
0.0.3 2018-12-27 增加追加行/列
------------------------------------------------------
矩阵的创建及其操作创建及其简单操作/运算
理论:
参考 OneThin // http://outofmemery.cn/code-snippet
/16991/go-language-matrix-operation
进行了主要运算和结构的补充与修改
------------------------------------------------------
注意事项:
1. r, c 是从零开始算的
------------------------------------------------------
*/
package goNum
import (
"fmt"
"strconv"
)
//数据结构定义----------------------------------------+
// Matrix 定义Matrix数据类型
type Matrix struct {
Rows, Columns int //行数和列数
Data []float64 //将矩阵中所有元素作为一维切片
}
//矩阵操作-------------------------------------------+
//通过行列号寻找指定矩阵位置在一维切片中的编号
func findIndex(r, c int, A *Matrix) int {
//r E [0, n), c E [0, n)
return r*A.Columns + c
}
// SetMatrix 设置指定行列的值
func (A *Matrix) SetMatrix(r, c int, val float64) {
if (r >= A.Rows) || (c >= A.Columns) {
panic("Error in goNum.(*Matrix).SetMatrix: Out of range")
}
A.Data[findIndex(r, c, A)] = val
}
// GetFromMatrix 获取指定行列的值
func (A *Matrix) GetFromMatrix(r, c int) float64 {
if (r >= A.Rows) || (c >= A.Columns) {
panic("Error in goNum.(*Matrix).GetFromMatrix: Out of range")
}
return A.Data[findIndex(r, c, A)]
}
// RowOfMatrix 获取指定行的值的切片
func (A *Matrix) RowOfMatrix(i int) []float64 {
if i >= A.Rows {
panic("Error in goNum.(*Matrix).RowOfMatrix: Out of range")
}
return A.Data[findIndex(i, 0, A):findIndex(i, A.Columns, A)]
}
// ColumnOfMatrix 获取指定列的值的切片
func (A *Matrix) ColumnOfMatrix(j int) []float64 {
if j >= A.Columns {
panic("Error in goNum.(*Matrix).ColumnOfMatrix: Out of range")
}
col := make([]float64, A.Rows)
for i := 0; i < A.Rows; i++ {
col[i] = A.RowOfMatrix(i)[j]
}
return col
}
// Transpose 矩阵转置
func (A *Matrix) Transpose() Matrix {
B := ZeroMatrix(A.Columns, A.Rows)
for i := 0; i < A.Rows; i++ {
for j := 0; j < A.Columns; j++ {
B.SetMatrix(j, i, A.GetFromMatrix(i, j))
}
}
return B
}
// AppendRow 追加一行,另外一种方法是追加数据到A.Data,测试显示其速度表现更差
func (A *Matrix) AppendRow(row []float64) Matrix {
//判断row长度是否等于A列数
if len(row) != A.Columns {
panic("Error in goNum.(*Matrix).AppendRow: Slice length error")
}
B := ZeroMatrix(A.Rows+1, A.Columns)
n := A.Rows * A.Columns
for i := 0; i < n; i++ {
B.Data[i] = A.Data[i]
}
for i := 0; i < len(row); i++ {
B.Data[n+i] = row[i]
}
return B
}
// AppendColumn 追加一列,对于多次调用,建议组合使用转置和追加行
func (A *Matrix) AppendColumn(col []float64) Matrix {
//判断row长度是否等于A列数
if len(col) != A.Rows {
panic("Error in goNum.(*Matrix).AppendColumn: Slice length error")
}
B := ZeroMatrix(A.Rows, A.Columns+1)
for i := 0; i < A.Rows; i++ {
for j := 0; j < A.Columns; j++ {
B.SetMatrix(i, j, A.GetFromMatrix(i, j))
}
B.SetMatrix(i, A.Columns, col[i])
}
return B
}
// PrintMatrix 格式输出
func (A *Matrix) PrintMatrix() {
//求出最长字符
colwidstr := make([]string, A.Columns)
for i := range colwidstr {
var maxLen int
thisColumn := A.ColumnOfMatrix(i)
for j := range thisColumn {
thisLen := len(strconv.FormatFloat(thisColumn[j], 'f', -1, 64))
if thisLen > maxLen {
maxLen = thisLen
}
}
}
for i := 0; i < A.Rows; i++ {
thisRow := A.RowOfMatrix(i)
fmt.Printf("[")
for j := range thisRow {
var format string
if j == 0 {
format = "%" + colwidstr[j] + "s"
} else {
format = " %" + colwidstr[j] + "s"
}
fmt.Printf(format, strconv.FormatFloat(thisRow[j], 'f', -1, 64))
}
fmt.Printf("]\n")
}
}
//矩阵初始化-----------------------------------------+
// ZeroMatrix r行c列零矩阵
func ZeroMatrix(r, c int) Matrix {
return Matrix{r, c, make([]float64, r*c)}
}
// IdentityE n阶单位矩阵
func IdentityE(n int) Matrix {
A := ZeroMatrix(n, n)
for i := 0; i < len(A.Data); i += (n + 1) {
A.Data[i] = 1.0
}
return A
}
// NewMatrix 以已有数据创建r行c列矩阵
func NewMatrix(r, c int, data []float64) Matrix {
if len(data) != r*c {
panic("goNum.Matrix.New: Length of data does not matched r rows and c columns")
}
A := ZeroMatrix(r, c)
A.Data = data
return A
}
// Slices1ToMatrix 一维切片转为矩阵(列向量)
func Slices1ToMatrix(s []float64) Matrix {
A := ZeroMatrix(len(s), 1)
for i := 0; i < A.Rows; i++ {
A.Data[i] = s[i]
}
return A
}
// Slices2ToMatrix 二维切片转为矩阵
func Slices2ToMatrix(s [][]float64) Matrix {
row := len(s)
col := len(s[0])
A := ZeroMatrix(row, col)
for i := 0; i < row; i++ {
for j := 0; j < col; j++ {
A.SetMatrix(i, j, s[i][j])
}
}
return A
}
// Matrix1ToSlices 列向量转为一维切片
func Matrix1ToSlices(A Matrix) []float64 {
s := make([]float64, A.Rows)
for i := 0; i < A.Rows; i++ {
s[i] = A.Data[i]
}
return s
}
// Matrix2ToSlices 二维矩阵转为二维切片
func Matrix2ToSlices(A Matrix) [][]float64 {
s := make([][]float64, A.Rows)
for i := 0; i < A.Rows; i++ {
s[i] = make([]float64, A.Columns)
for j := 0; j < A.Columns; j++ {
s[i][j] = A.GetFromMatrix(i, j)
}
}
return s
}
//矩阵运算------------------------------------------+
// AddMatrix 矩阵相加
func AddMatrix(A, B Matrix) Matrix {
if (A.Rows != B.Rows) || (A.Columns != B.Columns) {
panic("goNum.Matrix.Add: A and B does not matched")
}
AaddB := ZeroMatrix(A.Rows, A.Columns)
for i := 0; i < A.Rows; i++ {
for j := 0; j < A.Columns; j++ {
AaddB.SetMatrix(i, j, A.GetFromMatrix(i, j)+B.GetFromMatrix(i, j))
}
}
return AaddB
}
// SubMatrix 矩阵相减
func SubMatrix(A, B Matrix) Matrix {
if (A.Rows != B.Rows) || (A.Columns != B.Columns) {
panic("goNum.Matrix.Sub: A and B does not matched")
}
AsubB := ZeroMatrix(A.Rows, A.Columns)
for i := 0; i < A.Rows; i++ {
for j := 0; j < A.Columns; j++ {
AsubB.SetMatrix(i, j, A.GetFromMatrix(i, j)-B.GetFromMatrix(i, j))
}
}
return AsubB
}
// NumProductMatrix 矩阵数乘
func NumProductMatrix(A Matrix, c float64) Matrix {
cA := ZeroMatrix(A.Rows, A.Columns)
for i := 0; i < len(cA.Data); i++ {
cA.Data[i] = c * A.Data[i]
}
return cA
}
// DotPruduct 矩阵点乘
func DotPruduct(A, B Matrix) Matrix {
if A.Columns != B.Rows {
panic("goNum.Matrix.DotPruduct: A and B does not matched")
}
AdotB := ZeroMatrix(A.Rows, B.Columns)
for i := 0; i < A.Rows; i++ {
for j := 0; j < B.Columns; j++ {
for k := 0; k < A.Columns; k++ {
AdotB.Data[B.Columns*i+j] += A.GetFromMatrix(i, k) * B.GetFromMatrix(k, j)
}
}
}
return AdotB
}
// CrossVector 向量叉乘,得到垂直于两个向量所在平面的向量
func CrossVector(a, b []float64) []float64 {
if (len(a) != 3) || (len(b) != 3) {
panic("goNum.Matrix.CrossVector: vector a or b length is not 3")
}
acrossb := make([]float64, 3)
acrossb[0] = a[1]*b[2] - a[2]*b[1]
acrossb[1] = a[2]*b[0] - a[0]*b[2]
acrossb[2] = a[0]*b[1] - a[1]*b[0]
return acrossb
}
Go
1
https://gitee.com/caoweilin/goNum.git
git@gitee.com:caoweilin/goNum.git
caoweilin
goNum
goNum
master

搜索帮助