栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

实矩阵相乘

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

实矩阵相乘

实矩阵相乘 矩阵相乘

让我们先来了解矩阵是怎么相乘的:

矩阵 B B B与矩阵 A A A 相乘得矩阵 C C C: C = A × B C = A times B C=A×B
( c 0 c 1 c 2 c 3 ) = ( a 0 a 1 a 2 a 3 ) × ( b 0 b 1 b 2 b 3 ) begin {pmatrix} c_{0} & c_{1}\ c_{2} & c_{3} end {pmatrix} = begin {pmatrix} a_{0} & a_{1}\ a_{2} & a_{3} end {pmatrix} times begin {pmatrix} b_{0} & b_{1}\ b_{2} & b_{3} end {pmatrix} (c0​c2​​c1​c3​​)=(a0​a2​​a1​a3​​)×(b0​b2​​b1​b3​​)

其中有:
c 0 = a 0 × b 0 + a 1 × b 2 c 1 = a 0 × b 1 + a 1 × b 3 c 2 = a 2 × b 0 + a 3 × b 2 c 3 = a 2 × b 1 + a 3 × b 3 c_0 = a_0 times b_0 + a_1 times b_2\ c_1 = a_0 times b_1 + a_1 times b_3\\ c_2 = a_2 times b_0 + a_3 times b_2\ c_3 = a_2 times b_1 + a_3 times b_3 c0​=a0​×b0​+a1​×b2​c1​=a0​×b1​+a1​×b3​c2​=a2​×b0​+a3​×b2​c3​=a2​×b1​+a3​×b3​

其次,两个矩阵若要想相乘,需要满足:第一个矩阵的列数等于第二个矩阵的行数,如:
A m × n × B n × k = C m × k A_{m times n} times B_{n times k} = C_{m times k} Am×n​×Bn×k​=Cm×k​
好,复习完以上内容,我们就来看看如何编写程序来计算两个实矩阵相乘吧:

若要求 m × n m times n m×n阶矩阵 A A A与 n × k n times k n×k阶矩阵 B B B乘积矩阵 C = A B C=AB C=AB

我们就有矩阵 C C C各个元素的式子:
c i j = ∑ t = 0 n − 1 a i t b t j , i = 0 , 1 , . . . , m − 1 ; j = 0 , 1 , . . . , k − 1 c_{ij} = sum_{t = 0}^{n-1} a_{it}b_{tj}, i = 0, 1, ..., m-1;j = 0, 1, ..., k-1 cij​=t=0∑n−1​ait​btj​,i=0,1,...,m−1;j=0,1,...,k−1
如此归纳之后在运用计算机程序将矩阵 C C C计算出来便显得简单多了

我们将接口设为:void trmul(double* a, double* b, int m, int n, int k, double* c)

接口与参数说明:

形参与函数类型参数意义
double a[m][n]存放矩阵 A A A的元素
double b[n][k]存放矩阵 B B B的元素
int m矩阵 A A A 与乘积矩阵 C C C的行数
int n矩阵 A A A 的列数与矩阵 B B B的行数
k矩阵 B B B 与乘积矩阵 C C C的列数
double c[m][k]返回乘积矩阵 C = A B C=AB C=AB的元素

根据以上归纳的公式与接口参数说明,我们很容易就能写出计算两个实矩阵相乘的程序:

void turml(double* a, double* b, int m, int n, int k, double* c) {
    for(int i = 0; i < m; ++i) {
        for(int j = 0; j < k; ++j) {
            int u = i*k+j;
            c[u] = 0.0;   // 等价于 c[i][j] = 0.0;
            for(int t = 0; t < n; ++t) {
                c[u] += a[i*n+t] * b[t*k+j]; // 等价于c[i][j] = a[i][t]*b[t][j];
            }
        }
    }
}

我们来测试一下这个程序:

求下列矩阵 A A A与 B B B的乘积矩阵 C = A B C=AB C=AB:

其中 A A A 和 B B B为以下值:
A = ( 1 3 − 2 0 4 − 2 − 1 5 − 7 2 0 8 4 1 − 5 3 − 3 2 − 4 1 ) A = begin {pmatrix} 1 & 3 & -2 & 0 & 4\ -2 & -1 & 5 & -7 & 2\ 0 & 8 & 4 & 1 & -5\ 3 & -3 & 2 & -4 & 1 end {pmatrix} A=⎝⎜⎜⎛​1−203​3−18−3​−2542​0−71−4​42−51​⎠⎟⎟⎞​
B = ( 4 5 − 1 2 − 2 6 7 8 1 0 3 − 5 9 8 − 6 ) B = begin {pmatrix} 4 & 5 & -1\ 2 & -2 & 6\ 7 & 8 & 1\ 0 & 3 & -5\ 9 & 8 & -6 end {pmatrix}\ B=⎝⎜⎜⎜⎜⎛​42709​5−2838​−161−5−6​⎠⎟⎟⎟⎟⎞​
运行程序如下:

#include "turml.hpp"

int main() {
    double a[4][5] = {{1.0, 3.0, -2.0, 0.0, 4.0},
                      {-2.0, -1.0, 5.0, -7.0, 2.0},
                      {0.0, 8.0, 4.0, 1.0, -5.0},
                      {3.0, -3.0, 2.0, -4.0, 1.0}};
    double b[5][3] = {{4.0, 5.0, -1.0},
                      {2.0, -2.0, 6.0},
                      {7.0, 8.0, 1.0},
                      {0.0, 3.0, -5.0},
                      {9.0, 8.0, -6.0}};
    double c[4][3];

    turml((double*)a, (double*)b, 4, 5, 3, (double*)c);

    for(int i = 0; i != 4; ++i) {
        for(int j = 0; j != 3; ++j) {
            std::cout << c[i][j] << " ";
        }
        std::cout << std::endl;
    }


    return 0;
}

输出结果如下所示:

32 15 -9
43 27 24
-1 -21 77
29 33 -5

当然,因为C++对于二维数组的传参有很严格的限定,因此可以将普通传参转化为模板参数与普通参数混合的方法,以简化传参过程:

template 
void turml_tem(double a[M][N], double b[N][K], double c[M][K]) {
    for(int i = 0; i < M; ++i) {
        for(int j = 0; j < K; ++j) {
            c[i][j] = 0.0;
            for(int t = 0; t < N; ++t) {
                c[i][j] += a[i][t] * b[t][j];
            }
        }
    }
}

调用过程如下所示:

#include "turml.hpp"

int main() {
    double a[4][5] = {{1.0, 3.0, -2.0, 0.0, 4.0},
                      {-2.0, -1.0, 5.0, -7.0, 2.0},
                      {0.0, 8.0, 4.0, 1.0, -5.0},
                      {3.0, -3.0, 2.0, -4.0, 1.0}};
    double b[5][3] = {{4.0, 5.0, -1.0},
                      {2.0, -2.0, 6.0},
                      {7.0, 8.0, 1.0},
                      {0.0, 3.0, -5.0},
                      {9.0, 8.0, -6.0}};
    double c[4][3];

    turml_tem<4, 5, 3>(a, b, c);

    for(int i = 0; i != 4; ++i) {
        for(int j = 0; j != 3; ++j) {
            std::cout << c[i][j] << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/935886.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号