【问题标题】:C, matrix transposed multiplication using dynamic memory allocationC、矩阵转置乘法使用动态内存分配
【发布时间】:2025-11-27 19:50:02
【问题描述】:

基本上,我正在尝试转置和相乘一些矩阵 我得到 2 个矩阵,matrixAmatrixB 要执行的操作是 trace(transpose(matrixA)*matrixB)

我设法让它适用于 nxn 矩阵,但我无法让它适用于 mxn where(n>mm>n)。

我已经在网上寻找解决方案,但我无法将他们的解决方案应用到我的解决方案中。

我删除了几乎所有代码以简化阅读,如果您更喜欢整个代码I linked it here.

如果您确实想运行整个代码,请使用以下命令重新创建问题:

zeroes matrixA 2 3
zeroes matrixB 2 3
set matrixA
1 2 3 4 5 6
set matrixB
6 5 4 3 2 1
frob matrixA matrixB

上面的命令应该返回 Sum 56 但我得到 Sum 18

int* matrixATransposed = (int*) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
for (int i = 0; i < matrixARowLenght; i++)
{
    for (int j = 0; j < matrixAColLenght; j++)
    {
        *(matrixATransposed + i * matrixAColLenght + j) = *(matrixA + j * matrixAColLenght + i);
    }
}
// Multiply
int* mulRes = (int*)malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
for (int i = 0; i < matrixAColLenght; i++) {
    for (int j = 0; j < matrixBColLenght; j++) {
        *(mulRes + i * matrixARowLenght + j) = 0;
        for (int k = 0; k < matrixARowLenght; k++)
            *(mulRes + i * matrixAColLenght + j) += *(matrixATransposed + i * matrixAColLenght + k) * *(matrixB + k * matrixBColLenght + j);
    }
}
// Sum the trace
int trace = 0;
for (int i = 0; i < matrixARowLenght; i++) {
    for (int j = 0; j < matrixAColLenght; j++) {
        if (i == j) {
            trace += *(mulRes + i * matrixAColLenght + j);
        }
    }
}
printf_s("Sum: %d\n", trace);

【问题讨论】:

  • 也许如果你添加一些中间的printf's 来显示中间计算的结果,问题会变得更清楚。
  • 1.您需要决定是将矩阵表示为行主要顺序还是列主要顺序——因为您自己混淆了(在您提供的链接的代码中)。如果您有一个矩阵AnumARowsnumACols 总共有numARows * numACols 元素,并且您看到迭代如下:for(i=0; i &lt; numACols; ++i) for(j=0; j &lt; numARows; ++j) A[i*numACols+j]) - 那么你知道有问题 - 因为i 需要在 0 到 numARows-1 的范围内使其工作。记住最后一个元素是 numARows*numACols-1 = (numARows-1)*numACols + (numACols-1)。
  • 2.我会创建临时变量int matrixATransposedRowLength=matrixAColLength,以及matrixATransposedColLengthresRowLengthresColLength。并使用它们。
  • 3.您不需要用于跟踪的嵌套循环。一个循环就足够了。
  • 4.记得释放你的记忆。

标签: c matrix-multiplication transpose


【解决方案1】:

您用于计算转置、乘法和轨迹的数组索引似乎不正确。我已经在以下程序中更正了它们:

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv) {
    int matrixARowLenght = 2;
    int matrixAColLenght = 3;
    int matrixA[] = {1,2,3,4,5,6};

    int matrixBRowLenght = 2;
    int matrixBColLenght = 3; 
    int matrixB[] = {6,5,4,3,2,1};

    // Transpose
    int* matrixATransposed = (int *) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
    for (int i = 0; i < matrixAColLenght; i++) {
        for (int j = 0; j < matrixARowLenght; j++) {
            *(matrixATransposed + i * matrixARowLenght + j) = *(matrixA + j * matrixAColLenght + i);
        }
    }

    // Multiply
    int *mulRes = (int *) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
    for (int i = 0; i < matrixAColLenght; ++i) {
        for (int j = 0; j < matrixAColLenght; ++j) {
            *(mulRes + (i * matrixAColLenght) + j) = 0;
            for (int k = 0; k < matrixARowLenght; ++k) {
                *(mulRes + (i * matrixAColLenght) + j) += *(matrixATransposed + (i * matrixARowLenght) + k) * *(matrixB + (k * matrixAColLenght) + j);
            } 
        }
    }
    free(matrixATransposed);

    // Sum the trace
    int trace = 0;
    for (int i = 0; i < matrixAColLenght; i++) {
        for (int j = 0; j < matrixAColLenght; j++) {
            if (i == j) {
                trace += *(mulRes + i * matrixAColLenght + j);
            }
        }
    }
    printf("Sum: %d\n", trace);
    free(mulRes);

    return 0;
}

上面的程序会输出你的期望值:

Sum: 56


** 更新 **
正如 MFisherKDX 所指出的,如果结果矩阵不是方阵,上述代码将不起作用。下面的代码修复了这个问题:
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv) {
    int matrixARowLenght = 2;
    int matrixAColLenght = 3;
    int matrixA[] = {1,2,3,4,5,6};

    int matrixBRowLenght = 2;
    int matrixBColLenght = 4; 
    int matrixB[] = {8,7,6,5,4,3,2,1};

    // Transpose
    int* matrixATransposed = (int *) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
    for (int i = 0; i < matrixAColLenght; i++) {
        for (int j = 0; j < matrixARowLenght; j++) {
            *(matrixATransposed + i * matrixARowLenght + j) = *(matrixA + j * matrixAColLenght + i);
        }
    }

    // Multiply
    int *mulRes = (int *) malloc(matrixAColLenght * matrixBColLenght * sizeof(int));
    for (int i = 0; i < matrixAColLenght; ++i) {
        for (int j = 0; j < matrixBColLenght; ++j) {
            *(mulRes + (i * matrixBColLenght) + j) = 0;
            for (int k = 0; k < matrixARowLenght; ++k) {
                *(mulRes + (i * matrixBColLenght) + j) += *(matrixATransposed + (i * matrixARowLenght) + k) * *(matrixB + (k * matrixBColLenght) + j);
            } 
        }
    }
    free(matrixATransposed);

    // Sum the trace
    int trace = 0;
    for (int i = 0; i < matrixAColLenght; i++) {
        for (int j = 0; j < matrixBColLenght; j++) {
            if (i == j) {
                trace += *(mulRes + i * matrixBColLenght + j);
            }
        }
    }
    printf("Sum: %d\n", trace);
    free(mulRes);

    return 0;
}

此代码将按预期输出以下内容:

Sum: 83

【讨论】:

  • 这仅适用于您的结果矩阵是正方形的。例如,当结果矩阵的列多于行时,您的循环索引超出范围。
  • @MFisherKDX 感谢您指出这一点。我已经在我更新的帖子中解决了这个问题。