我有一个4 * 4矩阵,我想将它分成4个2 * 2矩阵块,这样我就可以将它们乘以不同的2 * 2矩阵。我怎么用C做到这一点?
A = [1 2 3 4; 2 3 4 5; 3 4 5 6; 4 5 6 7]
B = [2 3; 4 5]
我知道矩阵形式来自MATLAB,但它更容易在这里写出来。
万一你不清楚,我想把B乘以A的4个不同的块,即[1 2; 2 3],[3 4; 4 5],[3 4; 4 5]和[5 6; 6 7] ...
到目前为止,我所做的事情导致了糟糕的答案:
for (i = 1; i<= 4; i++)
{
for (j = 1; j<=4; j++)
{
C[i][j] = A[i][j]*B[i-2][j-2];
}
}
答案 0 :(得分:0)
如果您编写的是MATLAB脚本,我认为您想要这样做。
A11 = [11, 12; 21, 22];
A12 = [13, 14; 23, 24];
A21 = [31, 32; 41, 42];
A22 = [33, 34; 43, 44];
A = [A11, A12; A21, A22]
B = [11, 12; 21, 22]
C = [A11 * B, A12 * B; A21 * B, A22 * B]
如果我通过GNU Octave运行脚本 - 我建议将其作为MATLAB的大部分兼容free software替代品 - 它会产生以下输出:
A =
11 12 13 14
21 22 23 24
31 32 33 34
41 42 43 44
B =
11 12
21 22
C =
373 396 437 464
693 736 757 804
1013 1076 1077 1144
1333 1416 1397 1484
让我们看看如何在C中完成。
#include <stdio.h>
int
main()
{
int i, j;
int A[4][4] = {
{11, 12, 13, 14},
{21, 22, 23, 24},
{31, 32, 33, 34},
{41, 42, 43, 44},
};
int B[2][2] = {
{11, 12},
{21, 22},
};
int C[4][4] = {
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
};
for (i = 0; i < 4; i += 2)
{
for (j = 0; j < 4; j += 2)
{
/* For each 2 x 2 block with upper-left corner at (i, j). */
C[i + 0][j + 0] = A[i + 0][j + 0] * B[0][0] + A[i + 0][j + 1] * B[1][0];
C[i + 0][j + 1] = A[i + 0][j + 0] * B[0][1] + A[i + 0][j + 1] * B[1][1];
C[i + 1][j + 0] = A[i + 1][j + 0] * B[0][0] + A[i + 1][j + 1] * B[1][0];
C[i + 1][j + 1] = A[i + 1][j + 0] * B[0][1] + A[i + 1][j + 1] * B[1][1];
}
}
for (i = 0; i < 4; ++i)
printf("%8d%8d%8d%8d\n", C[i][0], C[i][1], C[i][2], C[i][3]);
return 0;
}
假设您了解线性代数的基本要素,我认为该程序不需要更多解释。我把它留作练习让你弄清楚最里面的循环中的模式,并将其重新编写为两个更多的嵌套循环。如果你的矩阵实际上只是2×2那么硬编码这样的索引可能是编写你的程序最可读的方式。随着矩阵变大,你真的想要一个循环。
C程序的输出是
373 396 437 464
693 736 757 804
1013 1076 1077 1144
1333 1416 1397 1484
恰好由GNU Octave脚本确认。
对于像这样的微小矩阵,性能几乎肯定不是问题。如果您正在处理更大的矩阵,那么您应该使用专用库(例如(C)BLAS)进行线性代数计算。 BLAS界面有一些陡峭的学习曲线,使用起来不是很方便。如果你有机会用C ++编程,那么有更多富有表现力的库,比如Eigen,可以达到相当的性能。