2

投稿のタイトルが私の質問に対応していると思います。しかし、繰り返しになりますが、私は誰かがこの問題に対してより良いアプローチを持っているかどうか疑問に思っています。

/* Write a recursive program to compute lg( N! ) */

#include <iostream>

#include <cmath>

using namespace std;

long double log_base2( long double N ) {
    return log( N )/log( 2.0 );
}

long double lg_n_factorial( long N ) {
    if( 1 == N ) return log_base2( static_cast<long double>( N ) );
    else return lg_n_factorial( N -1 ) + log_base2( static_cast<long double>( N ) );
}

int main( int argc, char *argv[] ) {
    cout << ( lg_n_factorial( 10 ) ) << endl;
    return 0;
}

人々の反応に基づいて、これは本の問題であり、本はそれを再帰的に行うように言っていることを明確にする必要があります。私はプログラミングの問題を練習していて、他の人からフィードバックを得ようとしているので、より良いプログラマーになるために取り組んでいるときに間違いを見つけることができます。

4

3 に答える 3

3

なぜ再帰を使用するのですか?反復ソリューションも同様に機能します。

long double lg_n_factorial( long N ) {
    long double result = 0;
    while (N > 1) {
        result += log_base2(static_cast<long double>(N));
        N--;
    } 
    return result;
}

このように、処理できる最大値はLONG_MAX、スタックがオーバーフローする前にスタックに収まる再帰呼び出しの数ではなく、の値によってのみ制約されます。

于 2011-08-08T05:13:07.413 に答える
2

繰り返し実行しますか?この問題を再帰的に解決する必要がある理由はわかりません。(何らかの理由で)再帰的に実行する必要がある場合、基本ケースは0を返すだけですが(任意のベースのlog(1)は0)、あなたの方法は正常に機能しているように見えます。

また、各ステップで2進数に変換する必要はありません。最後に1回変換できます。

于 2011-08-08T05:07:47.867 に答える
0

基本的な考え方は正しく理解できたと思います。文体の観点からは、returnステートメントが1つあり、それを使用するとコードが読みやすくなりますが?:、このような短いプログラムの場合、違いはごくわずかであり、心配する価値はありません。そして、もっと個人的な好みとして、末尾再帰であることを明確にするために、再帰を最後に配置します。(そして、末尾再帰を検出するコンパイラーは、算術を並べ替えて見つけることができるはずですが、人間の読者は、再帰が最後のものであるかどうかをより明確に理解します。)

于 2011-08-08T08:30:41.697 に答える