将方阵提高到C中N的幂

时间:2019-03-24 14:11:31

标签: c arrays pointers

我正在编写一个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循环的情况下编写指针。

1 个答案:

答案 0 :(得分:3)

您的代码中存在多个问题:

  • arrMult(int M, int M, int R[M][M], int X[M][M], int out[M][M])中有一个额外的论点
  • 如果outN == 0矩阵应设置为单位矩阵。
  • 如果out,则R矩阵应收到N == 1的副本。
  • 否则,outR 2 开始,但是您不太可能将与输入和输出相同的矩阵传递给arrMult。您应该使用临时矩阵存储结果并将其复制到out内或每次矩阵乘法之后的arrMult
  • 有一种效率更高的算法,可以以 log N 个步骤来计算功效,而不是发布的 N 个步骤:https://en.wikipedia.org/wiki/Exponentiation_by_squaring

这是一个简单的实现:

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;
}