cout语句如何影响所编写代码的O / P?

时间:2016-01-21 11:50:01

标签: c++ gcc

#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;

int main() {
    int t;
    double n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        double x;
        for(int i=1;i<=10000;i++)
        {
            x=n*i;
            if(x==ceilf(x))
            {
                cout<<i<<endl;
                break;
            }
        }
    }
    return 0;
}

对于I / P:

3
5
2.98
3.16

O / P:

1

如果我的代码是:

#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;

int main() {
    int t;
    double n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        double x;
        for(int i=1;i<=10000;i++)
        {
            x=n*i;
            cout<<"";//only this statement is added;
            if(x==ceilf(x))
            {
                cout<<i<<endl;
                break;
            }
        }
    }
    return 0;
}

对于相同的输入,O / P是:

1
50
25

第二个代码中添加的唯一额外行是:cout<<"";

任何人都可以帮助找出为什么仅仅因为第二个代码中添加的cout语句而导致输出存在这样的差异?

4 个答案:

答案 0 :(得分:4)

这是一个名副其实的Heisenbug。我尝试将您的代码删除到最小的复制示例,最后得到了这个(http://ideone.com/mFgs0S):

#include <iostream>
#include <math.h>

using namespace std;

int main()
{
    float n;
    cin >> n;  // this input is needed to reproduce, but the value doesn't matter
    n = 2.98;  // overwrite the input value
    cout << "";  // comment this out => y = z = 149
    float x = n * 50;   // 149
    float y = ceilf(x); // 150
    cout << "";  // comment this out => y = z = 150
    float z = ceilf(x); // 149
    cout << "x:" << x << " y:" << y << " z:" << z << endl;
}

ceilf的行为似乎取决于围绕它发生的iostream操作的特定顺序。不幸的是,目前我还没有更多细节调试的方法,但也许这将有助于其他人弄清楚发生了什么。无论如何,似乎几乎可以肯定它是gcc-4.9.2和gcc-5.1中的一个错误。 (你可以检查一下你在gcc-4.3.2中没有得到这种行为的想法。)

答案 1 :(得分:2)

“比较平等 浮点数学并不准确。像0.2这样的简单值无法使用二进制浮点数精确表示,浮点数的有限精度意味着操作顺序的微小变化可能会改变结果。不同的编译器和CPU架构以不同的精度存储临时结果,因此结果将根据您的环境的详细信息而有所不同。如果您进行计算,然后将结果与某些预期值进行比较,那么您很可能无法获得预期的结果。

换句话说,如果您进行计算然后进行此比较: if(result == expectedResult)

那么比较不太可能。如果比较为真,那么它可能不稳定 - 输入值,编译器或CPU的微小变化可能会改变结果并使比较变为假。“

来自http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm

希望这能回答你的问题。

你也遇到了问题

if(x==ceilf(x))

ceilf()返回一个浮点值,x声明为double。 请参阅problems in floating point comparison,了解为何不起作用。

将x更改为float并且程序运行正常,

答案 2 :(得分:2)

您可能遇到浮点表示问题 - 也就是说计算机无法完美地表示所有分数。所以当你看到50时,结果可能接近50.00000000001。在处理doublefloat时,这是一个非常常见的问题。

处理它的常用方法是定义一个非常小的常数(在数学术语中,这是Epsilon,这个数字只是“足够小”)

const double EPSILON = 0.000000001;

然后你的比较将从

改变
if (x==ceilf(x))

类似

double difference = fabs(x - ceilf(x));
if (difference < EPSILON)

这将消除你双打中那些微小的不准确之处。

答案 3 :(得分:0)

我在我的笔记本电脑甚至在线编译器上做了一个简单的尝试。
g ++(4.9.2-10)给出了所需的输出(3个输出),以及geeksforgeeks.org的在线编译器。然而,ideone,codechef没有给出正确的输出。
我可以推断的是,在线编译器将其编译器命名为&#34; C ++(gcc)&#34;并给出错误的输出。而geeksforgeeks.org,将编译器命名为&#34; C ++&#34;完美运行,以及g ++(在Linux上测试)。
因此,我们可以得出一个假设,即他们使用gcc编译C ++代码作为this link建议的方法。 :)