【问题标题】:Why different versions of same compiler is giving different outcomes?为什么同一编译器的不同版本会给出不同的结果?
【发布时间】:2019-07-26 09:35:26
【问题描述】:

我试图计算 nth 个谐波数。这是我的程序的主要 sn-p:

#include<cstdio>

int main(){
    int T; scanf("%d", &T);

    for (int C = 1; C <= T; C++){
        int n; scanf("%d", &n);
        long double H = 1;

        for (int i = 2; i <= n; i++)
            H += (1.0/i);

        printf("%.8lf\n", H);
    }

    return 0;
}

当我在我的机器上运行这个程序时(在 Code::Blocks IDE,编译器 gcc 5.1 中),一切似乎都很好。

输入:

10
1
2
3
4
5
6
7
8
9
10

输出:

1.000000
1.500000
1.833333
2.083333
2.283333
2.450000
2.592857
2.717857
2.828968
2.928968

但是当我在 online editor, it prints zero 中运行它时。这里,编译器是gcc 8.3

我想知道这种现象背后的原因以及避免这种情况的方法,以便获得预期的输出。

【问题讨论】:

  • 旁注:不要养成使用*scanf()(“扫描格式化数据”)扫描潜在格式错误(用户)输入的习惯。读取一行输入,然后使用更强大的功能(例如strtod())对其进行解析,从而提供更强大的行为。如果你必须使用*scanf()总是检查它的返回值以确保你确实确​​实将数据读入了你的变量。 -- 那是针对 C 的。对于 C++,您真的应该使用 &lt;iostream&gt; 而不是 &lt;cstdio&gt;...
  • 已确认建议

标签: c++ floating-point stdout codeblocks


【解决方案1】:

您应该打开编译器警告。它对这些事情有很大帮助。如果你会这样做,它会显示:

warning: format '%lf' expects argument of type 'double', but argument 3 has type 'long double' [-Wformat=]
   15 |         printf("Case %d: %lf\n", C, H);
      |                          ~~^        ~
      |                            |        |
      |                            double   long double
      |                          %Lf

所以这应该在两个版本中为您提供相似的结果:

int n; scanf("%d", &n);
long double H = 1;

for (int i = 2; i <= n; i++)
    H += (1.0/i);

printf("%.8Lf\n", H);

【讨论】:

  • 你知道,Code::Blocks 对用户非常友好,如果我忘记包含我正在使用的头文件,它有时不会显示编译错误在我的代码上运行。无论如何,如何启用编译器警告?我以为我已经默认启用了它们。
  • 不确定 Code::Blocks 是如何做到的,但编译器标志 -Wall -Wextra 对于大多数情况来说应该足够了。您可以静音不需要/不适用于您的案例的警告类型
  • 使用 Code::Blocks,可能会因版本而异。但是,通常情况下,打开警告的设置可以通过菜单“Project->Build Options ...”找到。这带来了一个带有许多选项卡的对话,其中一个是“编译器设置”。向下滚动并检查所需的警告(如果显示 + 符号,则隐藏一组选项,并且可能会展开标记为“警告”的选项)。至少检查“启用所有常见的编译器警告(覆盖许多其他设置)[-Wall]”和“启用严格的 ISO C 和 ISO C++ [-pedantic] 要求的警告”选项。
  • 请注意,“至少”实际上意味着“最低限度”。您确实应该查看编译器手册并运行尽可能严格的错误检查模式。从我的一个项目的 Makefile 中提取,像 -Wall -Wextra -pedantic -Wno-unused-parameter -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Winline -Wno-long-long -Wuninitialized 这样的东西绝不是矫枉过正。
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 2016-04-22
  • 2012-06-09
  • 1970-01-01
  • 1970-01-01
  • 2014-02-01
  • 2021-08-26
  • 1970-01-01
相关资源
最近更新 更多