【问题标题】:Two test cases giving me a nightmare两个测试用例让我做噩梦
【发布时间】:2021-12-14 21:07:26
【问题描述】:

这是一个代码,旨在将一个矩阵乘以另一个矩阵,同时跳过任何不必要的乘法(其中一个乘数为 0 的乘法) 我需要为课程提交它,但我一直被告知 10 例中有 2 例没有通过,我在这里做错了什么?我的意思是我知道它看起来很糟糕,而且效率远非理想,但我已经到了我只想完成这个的地步。

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

int main ()
{
    int anr, anc, bnr, bnc, i, j;
    scanf("%d", &anr);
    scanf("%d", &anc);
    int a[anr][anc];
    for (i=0; i<anr; i++)
    {
        for (j=0; j<anc; j++)
        {
            scanf("%d", &a[i][j]);
        }
    }
    scanf("%d", &bnr);
    scanf("%d", &bnc);
    int b[bnr][bnc];
    for (i=0; i<bnr; i++)
    {
        for (j=0; j<bnc; j++)
        {
            scanf("%d", &b[i][j]);
        }
    }
    if (anc!=bnr)
    {
        return 0;
    }
    else
    {
        int k;
        int out[anr][bnc];
        for (i=0;i<anr;i++)
        {
            for (j=0;j<bnc;j++)
            {
                out[i][j]=0;
                for (i=0;i<anr;i++)
        {
            for (j=0;j<bnc;j++)
            {
                out[i][j]=0;
                for (k=0;k<bnr;k++)
                {
                    if ((a[i][k]!=0) && (b[k][j]!=0))
                    {
                        out[i][j]=a[i][k]*b[k][j]+out[i][j];
                    }
                }
            }
        }
            }
        }
        for (i=0;i<anr;i++)
        {
            
            for (j=0;j<bnc;j++)
            {
                printf("%d ", out[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}

【问题讨论】:

  • 这是您的实际代码吗?您使用相同的 i/j 变量在两个循环中使用 i/j 变量启动两个循环?
  • 不理解以上内容,我立即怀疑在两个不同的地方做out[i][j]=0;
  • 看起来像一个非常困倦的学生的复制/粘贴错误。我的建议:休息一下:)
  • Welp,似乎代码正在运行,测试用例要求“无效”,以防矩阵的维度不适合乘法。谢谢大家的帮助。

标签: c sparse-matrix matrix-multiplication


【解决方案1】:

看起来您在编写代码和将其发布到此处之间的某个地方出现了复制/粘贴错误 - 您在同一变量的循环中循环 i 和 j!这显然是一个问题。在不知道您实际运行的代码是什么的情况下,无法详细说明具体细节,但有几件事可以更普遍地帮助您。

评论你的代码。我怎么强调都不为过。它在任何类型的编程中都很重要,但在数值算法中变得更加重要。不要依赖你的记忆——你会犯错误,那样你就会看不见它们。简单地浏览代码并注释每个操作会很明显,您循环两次索引并嵌套,但是很容易连续几个小时查看相同的代码并错过错误,因为它们成为风景的一部分。

其次,将逻辑分成尽可能小的部分。不是循环遍历结果的条目,而是将输出数组初始化为零,然后循环遍历内积的索引,将初始化移动到自己的循环中。将其移回单个循环是一项非常简单的任务,但是将其分开直到确保您拥有正确的代码是一种隔离问题并确保例如您没有在错误级别初始化为零的简单方法嵌套,或者在你计算了一些结果之后。

最后,检查每一步的工作。验证您读取的 a 值是否正确,然后对 b 执行相同操作。确保您的输出初始化为零。如果这些不正确并且您正在乘法代码中搜索问题,那么您将永远找不到问题。然后找到一个或多个失败的测试用例——打印出输入和你的输出。如果问题很明显,那就太好了。如果没有,看看你是否可以构建一个同样失败的更简单的例子,然后从那里开始。

这里的首要主题是尽可能简化和澄清代码。您需要在脑海中记录的越少,就越容易发现问题。如果你以后想压缩代码,很容易弄清楚每一部分的去向,如果你引入了一个问题,你就会确切地知道怎么做,因为你从正确的代码开始。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 2010-12-21
    • 2020-03-14
    • 2010-11-13
    • 2010-12-22
    相关资源
    最近更新 更多