在不同编译器上产生不同输出的代码

问题描述:

我在Codeforces上解决了Quasi-Binary问题(无所谓),这是我的submission。这是我产生的代码:在不同编译器上产生不同输出的代码

#include <iostream> 
#include <cmath> 

using namespace std; 

int quasi_binary(int num, int tens) 
{ 
    int res,digit; 

    if(num == 0) 
    { 
     return 0; 
    } 

    digit = num%10; 
    num = num/10; 

    res = quasi_binary(num, tens+1); 

    if(digit) 
    { 
     cout << 1; 
     return ((digit-1)*pow(10,tens)+res); 
    } 
    else 
    { 
     cout << 0; 
     return res; 
    } 
} 

int main() 
{ 
    int n,k=-1,temp,digit; 
    cin >> n; 

    //this loop calculates the value of k,as it needs to be printed first 
    temp=n; 
    while(temp) 
    { 
     digit = temp%10; 
     temp = temp/10; 

     if(digit>k) 
      k=digit; 
    } 
    cout << k << endl; 

    //print those k quasi-numbers 
    while(n) 
    { 
     n = quasi_binary(n,0); 
     cout << " "; 
    } 
    return 0; 
} 

我没有看到任何可能在不同编译器上产生未定义行为的语句。我在适当的地方使用了适当的括号,以避免模棱两可。仍然存在未定义的行为。任何人都可以请帮忙找到生成未定义行为的语句/指令。

输入

415 

输出(在线评测) - 不正确

5 
111 101 101 11 11 11 11 11 11 11 11 11 

输出(我的64位PC与海湾合作委员会上) - 正确

5 
111 101 101 101 1 
+2

'POW(10,十位)' - 如果你有整数指数不要使用'pow'。 [不保证pow会给你正确的结果](http://*.com/questions/25678481/why-pown-2-return-24-when-n-5/25678721#25678721)。 – PaulMcKenzie

+1

我不认为它与架构或编译器有关。测试数字是否大于零时,请使用完整的条件。即使用'if(num> 0)'而不是'if(num)'。不确定这是否是问题 – smac89

+1

*我没有看到任何可以在不同编译器上产生未定义行为的语句* - 但是您确实有产生浮点值的语句('pow()'),因此您的程序不是保证产生相同的结果。 – PaulMcKenzie

为避免将结果小于数学结果1,请将pow(10, tens)替换为int(0.5 + pow(10, tens))。或者,编写你自己的整数幂函数。

E.g.

using Int_noneg = int;  // "Not negative" 

auto int_pow(Int_noneg const x, Int_noneg const exponent) 
    -> int 
{ 
    Int_noneg reverse_bits = 0; 
    Int_noneg n_exponent_bits = 0; 
    for(Int_noneg i = exponent; i != 0; i /= 2) 
    { 
     reverse_bits = 2*reverse_bits + i%2; 
     ++n_exponent_bits; 
    } 

    Int_noneg result = 1; 
    for(Int_noneg i = 0; i < n_exponent_bits; ++i, reverse_bits /= 2) 
    { 
     result *= result; 
     if(reverse_bits % 2 != 0) { result *= x; } 
    } 
    return result; 
}; 

再进我的解决方案,我带着一个团队,去您在您的文章中引用的网站(并不需要这样做)。我提交了你发布的原始代码,是的,你得到的错误。因此,在我在主要评论部分中链接到的SO评论中,由于浮点和截断问题,pow函数确实会导致问题。

为了解决这个问题,你可以做几件事情,主要是给出的其他答案。不过,我会给我的解决方案:

unsigned long powTable[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 
          10000000, 100000000, 1000000000 }; 

//... 
return ((digit-1)*powTable[tens]+res); 

,而不是调用的pow功能,具有10个权力简单的查找表声明,然后tens被用作索引表。

Live Example

+0

嗯,我看不出这是对'int(0.5 + pow(10,几十))'的改进,无论是只需要一次的代码还是(特别是)更一般的可重用代码? –

+0

这是一个不使用'pow',而是使用查找表的替代解决方案。从未声称这是“更好”,只是一种选择。 – PaulMcKenzie