我刚刚(再次)实现了一个递归模板,用于在编译时计算整数的阶乘(谁曾想过有一天我真的需要它!)。尽管如此,我还是去Boost寻找答案,而不是自己动手。但是,特殊数学中的阶乘函数特别禁止它使用整数类型,所以我只写了自己的。
仍然,我应该使用Boost中的另一个功能吗?我应该将整数转换为double
并使用boost::factorial
函数吗?计算是在编译时执行的吗?
答案 0 :(得分:9)
你不需要Boost,如果你有C ++ 11,这只是1-liner:
constexpr uint64_t factorial(uint64_t n) {
return n == 0 ? 1 : n * factorial(n-1);
}
即使你的arg也不是编译时间常量,它也会工作。 uint64_t将与n< 21.
如果您在编译时执行此操作并乘以浮点值 - 则不会产生转换开销(转换也将在编译时进行)。
答案 1 :(得分: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上),我在程序集中看到它用常量24初始化fourFactorial
:
.loc 1 20 38 ## /Users/emile/Dev/sandbox/sandbox/main.cpp:20:38
movl $24, __ZZ4mainE13fourFactorial(%rip)
与使用递归编译时技巧相比,此方法可能导致更快的编译。