2016-07-24 14 views
2

私は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 

(GCCと私の64ビットPC上の)出力 - 正しい

5 
111 101 101 101 1 
+2

'POW(10、数十)' - あなたは、整数の指数を持っている場合は、 'pow'を使用しないでください。 Powがあなたに正しい結果をもたらすという保証はありません。(http://stackoverflow.com/questions/25678481/why-pown-2-return-24-when-n-5/25678721#25678721) – PaulMcKenzie

+1

私はそれがアーキテクチャやコンパイラとは関係ないと思います。数値が0より大きいかどうかをテストするときは、完全条件を使用します。私。 'if(num> 0)'ではなく 'if(num> 0)'を使います。これが問題であるかどうかわからない – smac89

+1

*異なるコンパイラで未定義の動作を引き起こす記述はありません* - しかし、浮動小数点値を生成する文( 'pow()')があります。同じ結果が得られることが保証されています。 – PaulMcKenzie

答えて

5

数値計算結果の1未満に丸めないようにするには、pow(10, tens)int(0.5 + pow(10, tens))に置き換えます。


または、独自の整数力関数を記述してください。

など。

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; 
}; 
0

私の解決策に入る前に、私はチームのために1つをとり、あなたの記事で参照したサイトに行った(これを行う必要はありませんでした)。投稿した元のコードを提出しました。はい、エラーが表示されます。したがって、私がメインのコメントセクションにリンクしているSOのコメントでは、pow関数は浮動小数点とトランケーションの問題のため実際に問題を引き起こします。

これを回避するには、できるだけいくつかのことがあります。ほとんどの場合、他の回答に概説されています。しかし、私は私の解決策を提供します:

pow関数を呼び出し、10の力を持つシンプルなルックアップテーブルが宣言され、その後、 tensは、テーブルへのインデックスとして使用される代わりに
unsigned long powTable[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 
          10000000, 100000000, 1000000000 }; 

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

Live Example

+0

私は、int(0.5 + pow(10、10))よりも、一回限りのコードか、より一般的な再利用可能なコードのどちらが改善したのか分かりません。 –

+0

これは 'pow'を使わない代わりの解決策ですが、ルックアップテーブルです。決してそれは単に「より良い」と主張したことはありません。 – PaulMcKenzie

関連する問題