6

コンパイル時に整数の階乗を計算するための再帰的なテンプレートを (もう一度) 実装しました (いつか実際に必要になると誰が思ったでしょう!)。それでも、私は自分自身を転がす代わりに、答えを探してBoostに行きました. ただし、特別な数学の階乗関数は、整数型での使用を明確に禁止しているため、独自に作成しました。

それでも、使用すべき Boost の別の機能はありますか? 整数を関数にキャストしてdouble使用する必要がありboost::factorialますか? 計算はコンパイル時に実行されますか?

4

2 に答える 2

9

Boost は必要ありません。C++11 を使用している場合、これは単なる 1 ライナーです。

constexpr uint64_t factorial(uint64_t n) { 
    return n == 0 ? 1  :  n * factorial(n-1); 
}

また、引数がコンパイル時定数でなくても機能します。uint64_t は n < 21 で動作します。

コンパイル時に実行し、浮動小数点値で乗算する場合、変換のオーバーヘッドはありません (変換もコンパイル時に行われます)。

于 2012-07-31T18:20:49.807 に答える
3

整数内に収まる階乗の数は限られているため、最初の 20 個の値を手動で事前に計算し、それらをグローバル配列または静的配列に格納するだけです。次に、グローバル関数または静的関数を使用して、配列内の階乗を検索します。

#include <iostream>

const int factorials[] =
{
    1,
    1,
    2,
    6,
    24,
    // etc...
};

inline const int factorial(int n) {return factorials[n];}

int main()
{
    static const int fourFactorial = factorial(4);
    std::cout << "4! = " << fourFactorial << "\n";
}

への引数としてリテラルを使用する場合factorial、コンパイラは単に関数呼び出しを結果に置き換える必要があります (最適化が有効になっている場合)。上記の例を XCode 4.4 (Mac 上) で試したところfourFactorial、定数 24で初期化されるアセンブリが表示されます。

.loc    1 20 38  ## /Users/emile/Dev/sandbox/sandbox/main.cpp:20:38
movl    $24, __ZZ4mainE13fourFactorial(%rip)

この方法は、再帰的なコンパイル時のトリックを使用するよりもコンパイルが高速になる場合があります。

于 2012-07-31T20:43:15.853 に答える