【问题标题】:Function to multiply 3x3 matrices gives wrong answer for middle column only乘以 3x3 矩阵的函数仅对中间列给出错误答案
【发布时间】:2020-11-03 06:48:18
【问题描述】:

在自学 c 时,我认为编写一个将两个 3x3 矩阵相乘然后使其更通用的函数是一个好习惯。该函数似乎计算了第一列和最后一列的正确结果,但不是中间列。此外,中间列下方的每个值都比上一个值多 3。

例如:

[1 2 3]   [23  4  6]
[4 5 6] * [ 2 35  0]
[7 8 9]   [14  2 43]

我收到的答案是:

[ 69  80 135]
[190 273 282]
[303 326 429]

实际答案应该是:

[ 69  83 135]
[190 279 282]
[303 335 429]

为了清楚起见,将中间的列分开:

Received  Expected
   [ 80]  [ 83]
   [273]  [279]
   [326]  [335]

我的代码如下:

#include <stdio.h>

typedef struct mat_3x3
{
    double values [3][3];
} mat_3x3;



void SetMatrix(mat_3x3 * matrix, double vals[3][3])
{
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            (matrix->values)[i][j] = vals[i][j];
        }
    }
    putchar('\n');
}



mat_3x3 MatrixMultiply(mat_3x3 * m1, mat_3x3 * m2)
{
    mat_3x3 result;
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            double temp = 0;
            for (int k = 0; k < 3; k++)
            {               
                temp += ((m1->values)[i][k] * (m2->values)[k][j]);
            }
            (result.values)[i][j] = temp;
        }
    }
    return result;
}



void PrintMatrix(mat_3x3 * matrix)
{
    putchar('\n');
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            printf("%lf  ", (matrix->values)[i][j]);
        }
        putchar('\n');
    }
    putchar('\n');
}



int main()
{
    mat_3x3 m1;
    mat_3x3 * pm1 = &m1;
    
    mat_3x3 m2;
    mat_3x3 * pm2 = &m2;
    
    double vals[3][3] = {
        {1,2,3},
        {4,7,6},
        {7,8,9}
    };
    
    double vals2[3][3] = {
        {23,4,6},
        {2,35,0},
        {14,2,43}
    };
    
    SetMatrix(pm1, vals);
    SetMatrix(pm2, vals2);
    
    printf("\nm1:");
    PrintMatrix(pm1);
    printf("\nm2:");
    PrintMatrix(pm2);
        
    mat_3x3 m3 = MatrixMultiply(pm1, pm2);
    mat_3x3 * pm3 = &m3;
    printf("\nm3 = m1 * m2");
    PrintMatrix(pm3);
    
}

已经研究了一段时间,现在将其与其他简单示例进行比较,但找不到问题,因此不胜感激!

此外,如果我在语法方面做了任何糟糕的事情等,我也愿意接受任何关于它的编写方式的批评。

【问题讨论】:

  • 不要从纯数学函数中打印。使用 memcpy 传输矩阵数据。
  • 我没有看到代码有问题。你认为你应该得到的答案是错误的。它实际上给出的答案是我从手工中得到的。
  • 关闭 3,关闭 6,关闭 9。嗯 - 与第一个矩阵的第三列保持相同的值。听起来对我来说是一个错过的补充。每次的结果都是 MatrixA.colum3 太小了。
  • PrintMatrix(pm4) 是未命中类型,现已更正。
  • 感谢您的帮助,我想我已经找到了问题所在。尝试了一个不同的在线计算器来检查答案,这次它匹配得很好。

标签: c


【解决方案1】:

在自学 c 时,我认为编写一个将两个 3x3 矩阵相乘然后使其更通用的函数是一个好习惯。该函数似乎计算了第一列和最后一列的正确结果,但不是中间列。此外,中间列下方的每个值都比上一个值多 3。

在实践中,使用 C 编码时,您应该注意以下问题:

如果您想进行严肃的科学计算,您可以考虑切换(为了表达)到functional 语言,例如Ocaml。如果您关心进行大量迭代计算(例如在finite element methods 中),您可以切换到OpenCLOpenACC

请注意,科学计算是一个非常困难的领域。

预计要花十年时间来学习它。


我也愿意接受任何关于它的写作方式的批评。

 mat_3x3 MatrixMultiply(mat_3x3 * m1, mat_3x3 * m2)

不寻常。为什么不返回一个指针(指向使用malloc 获得并正确初始化的新内存区域)?这可能会更快(一个指针通常是 8 个字节,一个 3x3 矩阵需要 72 个字节来复制)并使您能够编写像 MatrixMultiply(MatrixMultiply(M1, M2), MatrixAdd(M2, M3)) 这样的代码。当然,garbage collection(阅读GC handbook,考虑使用Boehm GC)就会成为问题。如果你使用Ocaml,系统GC会很有帮助。

【讨论】:

  • 说实话,我只是没有想到这一点。有什么特别的理由更受欢迎吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-11
  • 2017-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多