Boost C++ 库

...世界上最受尊敬和专业设计的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

PrevUpHomeNext

双阶乘

#include <boost/math/special_functions/factorials.hpp>
namespace boost{ namespace math{

template <class T>
T double_factorial(unsigned i);

template <class T, class Policy>
T double_factorial(unsigned i, const Policy&);

}} // namespaces

返回 i!!

最后的 策略 参数是可选的,可用于控制函数的行为:如何处理错误,使用什么级别的精度等。请参阅 策略文档 以获取更多详细信息。

如果结果太大而无法在类型 T 中表示,则可能返回 overflow_error 的结果。 该实现旨在针对可以进行 i! 表格查找的小 i 进行优化。

[Important] 重要提示

上面描述的函数是模板,其中模板参数 T 无法从传递给函数的参数中推导出来。 因此,如果您编写类似如下的代码

boost::math::double_factorial(2);

您将收到一个(可能令人困惑的)编译器错误,通常指示找不到这样的函数。 相反,您需要显式指定返回类型并编写

boost::math::double_factorial<double>(2);

以便知道返回类型。 此外,模板参数必须是实值类型,例如 floatdouble,而不是整数类型 - 整数类型太容易溢出!

源代码 static_assert 以及之后的注释将是

static_assert(!std::is_integral<T>::value, "Type T must not be an integral type");
// factorial<unsigned int>(n) is not implemented
// because it would overflow integral type T for too small n
// to be useful. Use instead a floating-point type,
// and convert to an unsigned type if essential, for example:
// unsigned int nfac = static_cast<unsigned int>(factorial<double>(n));
// See factorial documentation for more detail.
[Note] 注意

double_factorial 的参数类型为 unsigned,即使技术上定义了 -1!!。

精度

该实现使用了阶乘函数的简单适配,因此错误率应该不会比几个 epsilon 高。

测试

双阶乘的 spot 测试使用由 Wolfram Alpha 生成的数据。

实现

双阶乘是根据阶乘和伽玛函数实现的,使用以下关系式

(2n)!! = 2n * n!

(2n+1)!! = (2n+1)! / (2n n!)

(2n-1)!! = Γ((2n+1)/2) * 2n / sqrt(pi)


PrevUpHomeNext