我正在编写一个C程序来计算平方数组,并提高到N的幂。
我想将它们编写在单独的函数中以保持其清洁。我有一个功能
arrMult(int M, int R[M][M], int X[M][M], int out[M][M])
实际上是out = R*X
。为了将其提高到N次方,我编写了以下函数:
int arrNthPow(int M, int N, int R[M][M], int out[M][M])
{
// Initialize
arrPrint(M, M, out);
arrMult(M, R, R, out);
for (int i = 1; i < N - 1; i++){
arrPrint(M, M, out);
arrMult(M, R, out, out);
}
return 0;
}
但是,我意识到这并没有给我期望的结果。相反,如果我这样做
arrMult(M, R, R, out1);
arrMult(M, out1, R, out2);
arrMult(M, out2, R, out3);
out3
为我提供了所需的答案。我假设我必须以某种方式使用指针来复制arrMult
之后的每个数组输出的值,然后再将arrMult
用于下一次迭代,但是我不确定如何。
但是,我对指针不是很熟悉,也不知道如何在不将值复制到temp
变量和使用其他for循环的情况下编写指针。
答案 0 :(得分:3)
您的代码中存在多个问题:
arrMult(int M, int M, int R[M][M], int X[M][M], int out[M][M])
中有一个额外的论点out
,N == 0
矩阵应设置为单位矩阵。out
,则R
矩阵应收到N == 1
的副本。out
从R
2 开始,但是您不太可能将与输入和输出相同的矩阵传递给arrMult
。您应该使用临时矩阵存储结果并将其复制到out
内或每次矩阵乘法之后的arrMult
。这是一个简单的实现:
void arrIdentity(int M, int out[M][M]) {
/* initialize array to identity matrix. */
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
out[i][j] = (i == j);
}
}
}
void arrCopy(int M, const int mat[M][M], int out[M][M]) {
/* copy a matrix. */
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
out[i][j] = mat[i][j];
}
}
}
void arrMult(int M, const int R[M][M], const int X[M][M], int out[M][M]) {
/* compute matrix multiplication: out = R * X. */
int temp[M][M];
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
int sum = 0;
for (int k = 0; k < M; k++) {
sum += R[i][k] * X[k][j];
}
temp[i][j] = sum;
}
arrCopy(M, temp, out);
}
}
int arrNthPow(int M, int N, const int R[M][M], int out[M][M]) {
/* Naive matrix exponentiation */
if (N < 0)
return -1;
if (N == 0) {
arrIdentity(M, out);
return 0;
} else {
arrCopy(M, R, out);
for (int i = 1; i < N; i++) {
arrMult(M, R, out, out);
}
}
return 0;
}
使用Wikipedia文章中介绍的方法,这是一种更有效的替代方法:
int arrNthPow2(int M, int N, const int R[M][M], int out[M][M]) {
/* Matrix exponentiation by squaring */
int X[M][M];
if (N < 0)
return -1;
if (N == 0) {
arrIdentity(M, out);
return 0;
}
if (N == 1) {
arrCopy(M, R, out);
return 0;
}
if (N == 2) {
arrMult(M, R, R, out);
return 0;
}
arrIdentity(M, out);
arrCopy(M, R, X);
while (N > 1) {
if (N & 1)
arrMult(M, X, out, out);
arrMult(M, X, X, X);
N >>= 1;
}
arrMult(M, X, out, out);
return 0;
}