二维数组做函数参数与矩阵的相乘

二维数组做函数参数与矩阵的相乘

背景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
二维数组实验题:利用矩阵相乘公式,编程计算M*N阶矩阵A和N*M阶矩阵B之积C(M*M阶矩阵)。
要求如下:
1.用宏定义形式分别定义M、N的值为34
2.函数原型分别定义成:
void MultiplyMatrix(int a[M][N], int b[N][M], int c[M][M]);/* 函数功能:计算矩阵相乘之积,结果存于二维数组c中 */
void InputMatrixA(int a[M][N]);/* 函数功能:输入矩阵a中的元素 */
void InputMatrixB(int b[N][M]);/* 函数功能:输入矩阵b中的元素 */
void OutputMatrix(int a[M][M]);/* 函数功能:输出矩阵a中的元素 */
3.主函数定义成:
int main()
{
int a[M][N], b[N][M], c[M][M];
InputMatrixA(a);
InputMatrixB(b);
MultiplyMatrix(a,b,c);
OutputMatrix(c);
return 0;
}
4.输入输出格式:
输入矩阵A的提示:"Input %d*%d matrix a:\n"
输入矩阵A中元素的提示:"a[%d,%d]:"
输入矩阵A中元素的格式:"%d"
输入矩阵B的提示:"Input %d*%d matrix b:\n"
输入矩阵B中元素的提示:"b[%d,%d]:"
输入矩阵B中元素的格式:"%d"
输出结果提示:"Results:\n"
输出元素格式:"%6d"(注:每行末有printf("\n");)
程序运行示例:
Input 3*4 matrix a:↙
a[0,0]:1
a[0,1]:2
a[0,2]:3
a[0,3]:4
a[1,0]:1
a[1,1]:2
a[1,2]:3
a[1,3]:4
a[2,0]:1
a[2,1]:2
a[2,2]:3
a[2,3]:4
Input 4*3 matrix b:↙
b[0,0]:1
b[0,1]:2
b[0,2]:1
b[1,0]:2
b[1,1]:1
b[1,2]:2
b[2,0]:1
b[2,1]:2
b[2,2]:1
b[3,0]:2
b[3,1]:1
b[3,2]:2
Results:↙
16 14 16
16 14 16
16 14 16

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

#define M 3
#define N 4

void inputa(int a[][N]);
void inputb(int b[][M]);
void multi(int a[][N], int b[][M], int c[][M]);
void output(int c[][M]);

int main(void)
{
int a[M][N], b[N][M], c[M][M] = { 0 };

inputa(a);
inputb(b);
multi(a, b, c);
output(c);

return 0;
}

void inputa(int a[][N])
{
printf("Input %d*%d matrix a:\n", M, N);
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
printf("a[%d,%d]:", i, j);
scanf("%d", &a[i][j]);
}
}
}

void inputb(int b[][M])
{
printf("Input %d*%d matrix b:\n", N, M);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
printf("b[%d,%d]:", i, j);
scanf("%d", &b[i][j]);
}
}
}

void multi(int a[][N], int b[][M], int c[][M])
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < M; j++)
{
for (int k = 0; k < N; k++)
{
c[i][j] += a[i][k] * b[k][j];
}
}
}
}

void output(int c[][M])
{
printf("Results:\n");
for (int i = 0; i < M; i++)
{
for (int j = 0; j < M; j++)
{
printf("%6d", c[i][j]);
}
printf("\n");
}
}

矩阵的相乘:

假设:

$$A = \begin{bmatrix} \mathbf{1} & \mathbf{2} & \mathbf{3} \ 4 & 5 & 6 \end{bmatrix} \quad B = \begin{bmatrix} \mathbf{7} & 8 \ \mathbf{9} & 1 \ \mathbf{10} & 2 \end{bmatrix}$$

我们想算结果矩阵 左上角 的数:

  1. 取出 A 的第一行:[1, 2, 3]
  2. 取出 B 的第一列:[7, 9, 10] (注意是竖着的)
  3. 计算动作
    • $1$ 碰到了 $7 \rightarrow 1 \times 7 = 7$
    • $2$ 碰到了 $9 \rightarrow 2 \times 9 = 18$
    • $3$ 碰到了 $10 \rightarrow 3 \times 10 = 30$
  4. 求和:$7 + 18 + 30 = \mathbf{55}$

所以,结果矩阵的左上角就是 55。

怎么填满整个结果矩阵?

你就按照顺序重复上面的动作:

  1. A的第一行 $\times$ B的第一列 $\rightarrow$ 填在结果的 (0,0)

  2. A的第一行 $\times$ B的第二列 $\rightarrow$ 填在结果的 (0,1)

    (A的第一行用完了,换下一行)

  3. A的第二行 $\times$ B的第一列 $\rightarrow$ 填在结果的 (1,0)

  4. A的第二行 $\times$ B的第二列 $\rightarrow$ 填在结果的 (1,1)


我的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
void multi(int a[][N], int b[][M], int c[][M])
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < M; j++)
{
for (int k = 0; k < N; k++)
{
c[i][j] += a[i][k] * b[k][j];
}
}
}
}

需要在二维数组的循环基础上再套一个循环(如上定义变量k)

外层两个循环的 ij 为**c[i] [j]**服务,

内层循环计算c[i] [j]的值

第一次先计算c[0] [0]

c[0] [0] = a[0] [0] * b[0] [0]
+a[0] [1] * b[1] [0]
+a[0] [2] * b[2] [0]
+a[0] [3] * b[3] [0]

a的列在变化,小于a的列(N)

b的行在变化,小于b的行(N)

==总结==:c[i] [j] 指的是用a的第i行中的每一个数b的第j列中对应的数 再全部加起来

二维数组做参数的注意事项:

在函数声明中,可以省略第一维(行数),但绝对不能省略第二维(列数)。

  • 语法void func(int arr[][N], int rows)

  • 为什么:C语言中的二维数组在内存中是连续线性存储的(按行优先)。为了找到 arr[i][j],编译器在后台执行的计算公式是:

    $$Address = Base + (i \times \text{列数} + j) \times \text{数据大小}$$

    如果编译器不知道“列数”,它就无法算出下一行从哪里开始。


二维数组做函数参数与矩阵的相乘
http://example.com/2025/12/13/二维数组做函数参数与矩阵的相乘/
作者
王柏森
发布于
2025年12月13日
许可协议