从 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
然后,我们用所有阶乘填充 a 。我们还使用 aconstexpr
并使其成为带有可变参数包的模板。
我们用来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();
将为我们提供一个名为 Factorial 的编译时std::array<unsigned long long, 21>
,其中包含所有阶乘。如果我们需要第 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 开发、编译和测试
另外使用 gcc 10.2 和 clang 11.0.1 编译和测试
语言:C++17