【问题标题】:'using namespace std' is causing a strange behaviour“使用命名空间标准”导致奇怪的行为
【发布时间】:2017-03-11 06:34:45
【问题描述】:

我在同一组输入上运行了以下 2 个 sn-ps 代码,除了在第二个中使用“命名空间 std”之外,它们是相同的。我无法理解他们的输出不同的原因。有人可以指导我吗?谢谢!

方案一:

#include<cmath>
#include<cstdio>
//using namespace std;
int main() {
    int i, p, q, r, s;
    while (scanf("%d %d %d %d", &p, &q, &r, &s) == 4) {
        long double ans = 0;
        if (p - q < q)
            q = p - q;
        if (r - s < s)
            s = r - s;
        for (i = 1; i <= q; i++)
            ans += log(p - q + i) - log(i);
        for (i = 1; i <= s; i++)
            ans -= log(r - s + i) - log(i);
        printf("%.5lf\n", exp(ans));
    }
    return 0;
}

输出 1:

0.12587
505606.46055
1.28223
0.48996
2.00000
3.99960

http://ideone.com/x7n5cm

方案二:

#include<cmath>
#include<cstdio>
using namespace std;
int main() {
    int i, p, q, r, s;
    while (scanf("%d %d %d %d", &p, &q, &r, &s) == 4) {
        long double ans = 0;
        if (p - q < q)
            q = p - q;
        if (r - s < s)
            s = r - s;
        for (i = 1; i <= q; i++)
            ans += log(p - q + i) - log(i);
        for (i = 1; i <= s; i++)
            ans -= log(r - s + i) - log(i);
        printf("%.5lf\n", exp(ans));
    }
    return 0;
}

输出 2:

0.00000
0.00000
0.00000
0.00000
0.00000
0.00000

http://ideone.com/meDkRh

输入:

10 5 14 9
93 45 84 59
145 95 143 92
995 487 996 488
2000 1000 1999 999
9998 4999 9996 4998

修改: 1) 用标准头文件替换 #include "bits/stdc++.h"。 2) 用实际的代码片段替换图像。

【问题讨论】:

  • Get rid of the &lt;bits/stdc++.h&gt; stuff 并包含正确的标头,以便我们拥有可以正确分析的标准 C++ 程序。
  • @piyukr 我相信printf 中的正确格式应该是"%.5Lf"。您会看到流运营商确实有进步。
  • 无意冒犯,为什么这个问题会被否决?答案是否如此明显以至于不值得提出问题,还是我没有付出足够的努力,在我得到的指导下,在这里研究问题?
  • 张贴代码图片是不受欢迎的。邮政编码,不是图片。
  • @piyukr:是什么让你无法使用 CTRL+C 复制输出?即使 ideone.com 确实阻止了您将输出复制为文本(它没有),这仍然不意味着您不能将自己的源代码复制并粘贴为文本。

标签: c++ c++11 namespaces c++14 format-specifiers


【解决方案1】:

在摆弄log() 并怀疑operator += () 之后,我终于解决了这个难题。

实际错误是由printf("%.5lf\n", ...)引起的。

为了演示,我稍微修改了示例代码:

#include<cmath>
#include<cstdio>
#include<iomanip>
#include<iostream>
using namespace std;
int main() {
    int i, p, q, r, s;
    while (scanf("%d %d %d %d", &p, &q, &r, &s) == 4) {
        long double ans = 0;
        if (p - q < q)
            q = p - q;
        if (r - s < s)
            s = r - s;
        for (i = 1; i <= q; i++)
            ans += log(p - q + i) - log(i);
        for (i = 1; i <= s; i++)
            ans -= log(r - s + i) - log(i);
        printf("printf: %.5lf", exp(ans));
        cout << "\tcout: " << fixed << setprecision(5) << exp(ans) << endl;
    }
    return 0;
}

现在的输出是:

printf: 0.00000 cout: 0.12587
printf: 0.00000 cout: 505606.46055
printf: 0.00000 cout: 1.28223
printf: 0.00000 cout: 0.48996
printf: 0.00000 cout: 2.00000
printf: 0.00000 cout: 3.99960

我在ideone 上检查了这个。 当我在 Windows 10(64 位)上使用 VS2013 编译和运行它时得到相同的输出。

我也在 Windows 10(64 位)的 cygwin 中使用 gcc 进行了检查,得到以下输出:

$ g++ -std=c++11 -o test-longdouble test-longdouble.cc ; echo '10 5 14 9
> 93 45 84 59
> 145 95 143 92
> 995 487 996 488
> 2000 1000 1999 999
> 9998 4999 9996 4998
> ' | ./test-longdouble
printf: -0.00000        cout: 0.12587
printf: -4234002535919089587818586571373347278663379000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000        cout: 505606.46055
printf: -0.00000        cout: 1.28223
printf: -65094314467486612925155033958017324735054040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000     cout: 0.48996
printf: nan     cout: 2.00000
printf: nan     cout: 3.99960

$ g++ -std=c++14 -o test-longdouble test-longdouble.cc ; echo '10 5 14 9
93 45 84 59
145 95 143 92
995 487 996 488
2000 1000 1999 999
9998 4999 9996 4998
' | ./test-longdouble
printf: -0.00000        cout: 0.12587
printf: -4234002535919089587818586571373347278663379000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000        cout: 505606.46055
printf: -0.00000        cout: 1.28223
printf: -65094314467486612925155033958017324735054040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000     cout: 0.48996
printf: nan     cout: 2.00000
printf: nan     cout: 3.99960

$ g++ --version
g++ (GCC) 5.4.0

第一眼没看到,但cout 输出是正确的,只是printf 输出不同。

考虑到printf 格式化程序选择错误,您不应该对它的效果有任何期望

然后我修复了printf()中的错误格式:

#include<cmath>
#include<cstdio>
#include<iomanip>
#include<iostream>
using namespace std;
int main() {
  int i, p, q, r, s;
  while (scanf("%d %d %d %d", &p, &q, &r, &s) == 4) {
    long double ans = 0;
    if (p - q < q)
      q = p - q;
    if (r - s < s)
      s = r - s;
    for (i = 1; i <= q; i++)
      ans += log(p - q + i) - log(i);
    for (i = 1; i <= s; i++)
      ans -= log(r - s + i) - log(i);
    printf("printf: %.5Lf", exp(ans));
    cout << "\tcout: " << fixed << setprecision(5) << exp(ans) << endl;
  }
  return 0;
}

在 Windows 10(64 位)的 cygwin 中使用 gcc 再次编译和测试:

$ g++ -std=c++14 -o test-longdouble test-longdouble.cc ; echo '10 5 14 9
93 45 84 59
145 95 143 92
995 487 996 488
2000 1000 1999 999
9998 4999 9996 4998
' | ./test-longdouble
printf: 0.12587 cout: 0.12587
printf: 505606.46055    cout: 505606.46055
printf: 1.28223 cout: 1.28223
printf: 0.48996 cout: 0.48996
printf: 2.00000 cout: 2.00000
printf: 3.99960 cout: 3.99960

因此,我只能重复我在评论中已经说过的内容:您确实应该使用 C++ 流输出。 printf() 可能由于格式化程序中最轻微的错误而导致奇怪的行为。

【讨论】:

  • 您的代码在 ideone 上运行良好。但是,当我在计算机上运行时,输出不正确。见imgur.com/a/Gxw9Q
  • @piyukr 好的。在您的代码中,您没有使用标准标题。这可以解释不同的行为吗?
  • 抱歉,打错了。我再次运行程序,这次使用标准标题。见imgur.com/a/MwFs6
  • @piyukr 我在 cygwin 上做了,得到了同样的垃圾。所以呢?我试过-std=c++11-std=C++14。没有不同。我的 gcc 版本:5.4.0。 ideone中的一个:6.3。这可能是区别吗?
  • @piyukr 我也用 VS2013(部分 C++11、Windows 10、64 位)对此进行了测试。它在那里工作,就像我的回答中所说的那样。我们是否发现了 gcc
猜你喜欢
  • 2012-08-26
  • 2011-10-03
  • 1970-01-01
  • 2020-01-14
  • 1970-01-01
  • 2020-03-31
  • 1970-01-01
  • 2023-01-13
  • 2011-08-29
相关资源
最近更新 更多