2021年から更新。C++17が手元にある。
以下より速い方法はないと思います。アセンブラは必要ありません。
符号なし64ビット値に適合する階乗の数は非常に少ないため(21)、コンパイル時のconstexpr配列は主に21 * 8=168バイトのみを使用します。
168バイト
その数は非常に少ないため、コンパイル時間を簡単に構築して、constexpr std::array
それ以上の考慮事項をすべて停止できます。
実際、すべてはコンパイル時に実行できます。
最初に、階乗をconstexpr
関数として計算するためのデフォルトのアプローチを定義します。
constexpr unsigned long long factorial(unsigned long long n) noexcept {
return n == 0ull ? 1 : n * factorial(n - 1ull);
}
これにより、階乗はコンパイル時に簡単に計算できます。次に、std::array
すべての階乗を入力します。また、を使用constexpr
して、可変個引数パラメーターパックを使用したテンプレートにします。
std::integer_sequence
インデックス0、1、2、3、4、5、...の階乗を作成するために使用します。
それは単純で複雑ではありません。
template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
return std::array<unsigned long long, sizeof...(ManyIndices)>{ { factorial(ManyIndices)... } };
};
この関数には整数シーケンス0、1、2、3、4、...が供給されstd::array<unsigned long long, ...>
、対応する階乗とともにaが返されます。
最大21個の値を保存できることがわかっています。したがって、次の関数を作成します。これは、次のように、整数シーケンス1,2,3,4、...、20,21で上記を呼び出します。
constexpr auto generateArray()noexcept {
return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}
そして今、ついに、
constexpr auto Factorial = generateArray();
std::array<unsigned long long, 21>
すべての階乗を含むFactorialという名前のコンパイル時が表示されます。そして、i番目の階乗が必要な場合は、単純にと書くことができますFactorial[i]
。実行時に計算は行われません。
階乗を計算するより速い方法があるとは思いません。
以下の完全なプログラムをご覧ください。
#include <iostream>
#include <array>
#include <utility>
// ----------------------------------------------------------------------
// All the below will be calculated at compile time
// constexpr factorial function
constexpr unsigned long long factorial(unsigned long long n) noexcept {
return n == 0ull ? 1 : n * factorial(n - 1ull);
}
// We will automatically build an array of factorials at compile time
// Generate a std::array with n elements
template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
return std::array<unsigned long long, sizeof...(ManyIndices)>{ { factorial(ManyIndices)... } };
};
// Max index for factorials for an 64bit unsigned value
constexpr size_t MaxIndexFor64BitValue = 21;
// Generate the required number of elements
constexpr auto generateArray()noexcept {
return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}
// This is an constexpr array of all factorials numbers
constexpr auto Factorial = generateArray();
// All the above was compile time
// ----------------------------------------------------------------------
// Test function
int main() {
for (size_t i{}; i < MaxIndexFor64BitValue; ++i)
std::cout << i << '\t' << Factorial[i] << '\n';
return 0;
}
Microsoft Visual Studio Community 2019バージョン16.8.2で開発、コンパイル、テストされています
さらに、gcc10.2およびclang11.0.1でコンパイルおよびテストされています
言語:C ++ 17