2013-04-08 10 views
5

初めての投稿ですが、この質問が受け入れられることを願っています。反復と再帰を使用して階乗を計算するときの回答が異なります

小さなテストとして、繰り返しと再帰の両方を使用して数値の階乗を計算するアプリケーションを作成しました。これは、例えば24

より大きい数値の階乗を計算しようとすると、24の階乗を計算するときに25の階乗を計算する場合、両方の方法は62044840173323941.

の正しい答えを与える以外正常に動作するように見えましたしかし、答えは異なります。再帰的方法では1.5511210043330986e + 025となり、反復法では1.5511210043330984e + 025となります。

Wolfram Alphaによると、正しい答えは反復法と同じでなければならないので、関数間の矛盾はなぜですか?私は同僚に尋ねましたが、彼らはまたその行動を説明することができません。

#define TEST_CASE 25 

double GetFactorialRecursive(double i) 
{ 
    if (i == 1) 
    return i; 
    else 
    return i * GetFactorialRecursive(i - 1); 
} 

double GetFactorialIterative(double i) 
{ 
    double result = 1.0; 
    for (; i > 0; --i) 
     result *= i; 
    return result; 
} 

int main() 
{ 
double recres = 0, itrres = 0; 
recres = GetFactorialRecursive(TEST_CASE); 
itrres = GetFactorialIterative(TEST_CASE); 

if (recres != itrres) 
    std::cout << "Error" << "\n"; 
std::cout << std::setprecision(25) << "Recursion: " << recres << ", Iteration: " << itrres << "\n"; 
return 0; 

}

ご検討いただき、ありがとうございます。

+3

私はこれを自分で試しました。同様の結果、2つの数値が1つのビットだけ異なっていることも注目に値する: 'Recursion:15511210043330986055303168 [4529a940c33f6121]と' Iteration:15511210043330983907819520 [4529a940c33f6120] – benzado

答えて

9

再帰バージョンは5 *(4 *(3 *(2 * 1)))

反復バージョンは、1 *(2 *(3 *(4 * 5)))

を算出する算出演算の順序の違いによって、浮動小数点演算のラウンド方法が変更され、結果が異なります。

+2

この場合、浮動小数点が丸められる理由は、double型最大約15〜17桁の有効数字だけを保持することができ、 'n!'' n 'の値が比較的小さい場合でも、15〜17桁を超える傾向があります。一方、Wolfram | Alphaは、これらの種類の量を扱うときは、 'double'以外の全く異なる方法を使います。 –

2

浮動小数点の丸めによって、乗算の順序が異なり、結果が異なります。

あなたは(iから1にではなく)i1から行くためにforループを変更する場合は、再帰的なバージョンと同じ結果を得る必要があります。

+0

Drew Dormannが指摘したように、実際には、レジスタ<->のメモリ移行も、レジスタが(より高い精度を持つ傾向があるため)コード生成後にまったく同じものではない場合があります。 –

4

タイプdoublenot an exact typeです。それは正しい値の近似値であることを約束します。

したがって、両方の実装が正確であるとは限りません。

あなたの実装が異なる答えを引き起こす可能性があることをの要因があると懸念しています。

  1. あなたが乗算を異なる方法で注文しています。
  2. 反復バージョンは、同じ変数のすべての数式を実行します。インテル互換アーキテクチャ(x86およびx86-64)では、浮動小数点レジスタにの80ビットのが使用され、その精度はレジスタがメモリに格納されるまで維持されます。
+0

+1 (変数をメモリに戻すのではなくレジスタに保持する)最適化が実際にプログラムの観察可能な振る舞いを変えることができるのはPITAです –

関連する問題