C++中boost库的官方文档证实了-1!!定义。然而,当我试图计算-1的二重阶乘时,它会抛出以下错误"函数boost::math::tgamma中的错误gamma的结果太大,无法表示"。我可以实现基于迭代的代码来计算相同的代码(如果需要的话(,但我希望尽可能使用优化的库。对纠正这个问题有什么建议吗?
#include <iostream>
#include <boost/math/special_functions/factorials.hpp>
int main(int argc, char const *argv[]) {
double t = boost::math::double_factorial<double>(-1);
std::cout << t <<"n";
return 0;
}
这是最小的工作示例。
这就是boost::math::double_factorial
的声明方式:
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
根据boost::math::double_factorial
文件
double_factoral的参数类型为unsigned,即使技术上-1!!定义。
这意味着,尽管在数学上-1!!定义良好,函数不支持负输入。事实上,-1将被静默地转换为unsigned
,这将导致一个大的数字,从而导致溢出。
作为一种变通方法,您可以在namespace boost::math
中声明一个额外的double_factorial
函数
例如,为了简单起见,我只允许-1!!。
#include <iostream>
#include <exception>
#include <boost/math/special_functions/factorials.hpp>
namespace boost { namespace math {
template <class T>
T double_factorial(int i) { if (i == -1) return T{1}; else throw(std::runtime_error("Unknown double factorial")); }
} }
int main(int argc, char const *argv[]) {
double t = boost::math::double_factorial<double>(-1);
std::cout << t <<"n";
return 0;
}
在Coliru 上实时观看
警告
此解决方案将起作用,因为当您使用负参数调用double_factorial
时,编译器将在同一命名空间内选择新的重载。然而,这是潜在的危险:如果boost
的未来版本允许负值,代码可能不再编译,或者忽略新的boost版本。
一个更好的解决方案是将double_gamma
封装到您定义的函数中,如下所示
template <class T>
T my_double_factorial(int i) {
if (i > 0)
return boost::math::double_factorial<T>(i);
else if (i == -1)
return T{1};
else
throw(std::runtime_error("Unknown double factorial"));
}
函数被声明为
template <class T>
T double_factorial(unsigned i);
并且CCD_ 9是一个非常大的数字。