计算负实数值的 Gamma 函数(C++,Boost)
calculating the Gamma function for negative real values (C++, Boost)
以下无穷大需要计算非整数、负数、实数的阶乘:
(这是一种计算椭圆周长的方法,a和b是半长轴和半短轴,h定义为:
h = (a-b)^2/(a+b)^2)
阶乘函数可以通过为所有非负整数的实数定义的 Gamma 函数扩展为负值。
在编写严肃的代码时,我尝试了 boost::math::factorial 和 boost::math::tgamma,它们给出的结果仅低至 -1(不包括)-1.5 例如给出错误。
#include <iostream>
#include <boost/math/special_functions/factorials.hpp>
int main()
{
double x;
double f;
double tg;
x = -0.5;
f = boost::math::factorial<double>(x);
tg = boost::math::tgamma<double>(x);
cout << "factorial of " << x << " = " << f << endl;
cout << "tgamma of " << x << " = " << tg << endl << endl;
x = -1.5;
f = boost::math::factorial<double>(x);
tg = boost::math::tgamma<double>(x);
cout << "factorial of " << x << " = " << f << endl;
cout << "tgamma of " << x << " = " << tg << endl << endl;
return 0;
}
输出:
factorial of -0.5 = 1
tgamma of -0.5 = -3.54491
terminate called after throwing an instance of 'boost::exception_detail::clone_implboost::exception_detail::error_info_injector<std::domain_error >'
what(): Error in function boost::math::tgamma(long double): Evaluation of tgamma at a negative integer 0.
Aborted (core dumped)
提升阶乘:
boost factorial
提升 tgamma:
boost tgamma
我的问题:
- 是否有替代 boost 的方法可以计算其负域的伽玛函数?
- 我在上面链接的 boost 文档中找不到阶乘和 tgamma 函数的实现域。事实上,我可能只是错误地使用了它们。确定 domain/correct 用法的方法是什么?
谢谢。
我刚刚尝试在 Mac 上使用 g++-10 重现您的问题,使用 boost.math 提交哈希 87929356790ad0(当前 develop
),但我得到:
factorial of -0.5 = 1
tgamma of -0.5 = -3.54491
factorial of -1.5 = 1
tgamma of -1.5 = 2.36327
所以需要更多信息,Boost 版本,OS,编译器等等。
自 C++11 [1] 以来,伽马函数是标准库的一部分。
用法如下:
#include <cmath>
std::tgamma(-0.5) # -3.5449077
std::lgamma(-0.5) # 1.2655121
您不妨使用 tgammal
和 tgammaf
对应 long double
和 float
类型。
我知道出了什么问题。 boost::math::factorial
函数接受一个 unsigned
整数 根据定义 :
template <class T>
inline T factorial(unsigned i)
{
return factorial<T>(i, policies::policy<>());
}
这意味着如果您使用双精度调用它,它将隐式转换为无符号。那不是你想要的。此外,factorial
最终在内部使用 tgamma
,所以你得到这个:
#include <boost/math/special_functions/factorials.hpp>
#include <iostream>
void foo(long double x) {
using namespace boost::math;
try {
auto f = factorial<long double>(x);
std::cout << "factorial of " << static_cast<unsigned>(x) << " = " << f << "\n";
} catch(std::exception const& e) {
std::cout << "error at " << static_cast<unsigned>(x) << ": " << std::quoted(e.what()) << "\n";
}
}
int main() {
std::cout << std::unitbuf;
foo(-2);
}
最终会这样做:
#0 boost::math::tgamma<long double, boost::math::policies::policy<boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy> > (a=4294967295, z=...)
at /home/sehe/custom/boost_1_73_0/boost/math/special_functions/gamma.hpp:1994
No locals.
#1 0x0000555555558eb3 in boost::math::factorial<long double, boost::math::policies::policy<boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy> > (i=4294967294, pol=...)
at /home/sehe/custom/boost_1_73_0/boost/math/special_functions/factorials.hpp:44
result = -0.667762310955655363645
#2 0x0000555555558674 in boost::math::factorial<long double> (i=4294967294)
at /home/sehe/custom/boost_1_73_0/boost/math/special_functions/factorials.hpp:53
No locals.
#3 0x0000555555557792 in foo (x=-2) at /home/sehe/Projects/Whosebug/test.cpp:7
f = <invalid float value>
#4 0x000055555555791f in main () at /home/sehe/Projects/Whosebug/test.cpp:16
No locals.
所以它试图给你boost::math::factorial<long double> (i=4294967294)
修复
除了非负整数,不要使用 factorials
。
#include <boost/math/special_functions/factorials.hpp>
#include <iostream>
void foo(long double x) {
using namespace boost::math;
try {
auto tg = tgamma<long double>(x);
std::cout << "tgamma of " << x << " = " << tg << "\n" << std::endl;
} catch(std::exception const& e) {
std::cout << "error at " << x << ": " << std::quoted(e.what()) << std::endl;
}
}
int main() {
for (auto x : { 1., 2., 3., 4., 5., -.2, -2., -.5, -1.5 })
foo(x);
}
打印:
tgamma of 1 = 1
tgamma of 2 = 1
tgamma of 3 = 2
tgamma of 4 = 6
tgamma of 5 = 24
tgamma of -0.2 = -5.82115
error at -2: "Error in function boost::math::tgamma<long double>(long double): Evaluation of tgamma at a negative integer -2."
tgamma of -0.5 = -3.54491
tgamma of -1.5 = 2.36327
它在 -2
溢出是可以理解的,但这是正确的。
以下无穷大需要计算非整数、负数、实数的阶乘:
(这是一种计算椭圆周长的方法,a和b是半长轴和半短轴,h定义为:
h = (a-b)^2/(a+b)^2)
阶乘函数可以通过为所有非负整数的实数定义的 Gamma 函数扩展为负值。
在编写严肃的代码时,我尝试了 boost::math::factorial 和 boost::math::tgamma,它们给出的结果仅低至 -1(不包括)-1.5 例如给出错误。
#include <iostream>
#include <boost/math/special_functions/factorials.hpp>
int main()
{
double x;
double f;
double tg;
x = -0.5;
f = boost::math::factorial<double>(x);
tg = boost::math::tgamma<double>(x);
cout << "factorial of " << x << " = " << f << endl;
cout << "tgamma of " << x << " = " << tg << endl << endl;
x = -1.5;
f = boost::math::factorial<double>(x);
tg = boost::math::tgamma<double>(x);
cout << "factorial of " << x << " = " << f << endl;
cout << "tgamma of " << x << " = " << tg << endl << endl;
return 0;
}
输出:
factorial of -0.5 = 1
tgamma of -0.5 = -3.54491
terminate called after throwing an instance of 'boost::exception_detail::clone_implboost::exception_detail::error_info_injector<std::domain_error >' what(): Error in function boost::math::tgamma(long double): Evaluation of tgamma at a negative integer 0. Aborted (core dumped)
提升阶乘:
boost factorial
提升 tgamma:
boost tgamma
我的问题:
- 是否有替代 boost 的方法可以计算其负域的伽玛函数?
- 我在上面链接的 boost 文档中找不到阶乘和 tgamma 函数的实现域。事实上,我可能只是错误地使用了它们。确定 domain/correct 用法的方法是什么?
谢谢。
我刚刚尝试在 Mac 上使用 g++-10 重现您的问题,使用 boost.math 提交哈希 87929356790ad0(当前 develop
),但我得到:
factorial of -0.5 = 1
tgamma of -0.5 = -3.54491
factorial of -1.5 = 1
tgamma of -1.5 = 2.36327
所以需要更多信息,Boost 版本,OS,编译器等等。
自 C++11 [1] 以来,伽马函数是标准库的一部分。
用法如下:
#include <cmath>
std::tgamma(-0.5) # -3.5449077
std::lgamma(-0.5) # 1.2655121
您不妨使用 tgammal
和 tgammaf
对应 long double
和 float
类型。
我知道出了什么问题。 boost::math::factorial
函数接受一个 unsigned
整数 根据定义 :
template <class T>
inline T factorial(unsigned i)
{
return factorial<T>(i, policies::policy<>());
}
这意味着如果您使用双精度调用它,它将隐式转换为无符号。那不是你想要的。此外,factorial
最终在内部使用 tgamma
,所以你得到这个:
#include <boost/math/special_functions/factorials.hpp>
#include <iostream>
void foo(long double x) {
using namespace boost::math;
try {
auto f = factorial<long double>(x);
std::cout << "factorial of " << static_cast<unsigned>(x) << " = " << f << "\n";
} catch(std::exception const& e) {
std::cout << "error at " << static_cast<unsigned>(x) << ": " << std::quoted(e.what()) << "\n";
}
}
int main() {
std::cout << std::unitbuf;
foo(-2);
}
最终会这样做:
#0 boost::math::tgamma<long double, boost::math::policies::policy<boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy> > (a=4294967295, z=...)
at /home/sehe/custom/boost_1_73_0/boost/math/special_functions/gamma.hpp:1994
No locals.
#1 0x0000555555558eb3 in boost::math::factorial<long double, boost::math::policies::policy<boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy> > (i=4294967294, pol=...)
at /home/sehe/custom/boost_1_73_0/boost/math/special_functions/factorials.hpp:44
result = -0.667762310955655363645
#2 0x0000555555558674 in boost::math::factorial<long double> (i=4294967294)
at /home/sehe/custom/boost_1_73_0/boost/math/special_functions/factorials.hpp:53
No locals.
#3 0x0000555555557792 in foo (x=-2) at /home/sehe/Projects/Whosebug/test.cpp:7
f = <invalid float value>
#4 0x000055555555791f in main () at /home/sehe/Projects/Whosebug/test.cpp:16
No locals.
所以它试图给你boost::math::factorial<long double> (i=4294967294)
修复
除了非负整数,不要使用 factorials
。
#include <boost/math/special_functions/factorials.hpp>
#include <iostream>
void foo(long double x) {
using namespace boost::math;
try {
auto tg = tgamma<long double>(x);
std::cout << "tgamma of " << x << " = " << tg << "\n" << std::endl;
} catch(std::exception const& e) {
std::cout << "error at " << x << ": " << std::quoted(e.what()) << std::endl;
}
}
int main() {
for (auto x : { 1., 2., 3., 4., 5., -.2, -2., -.5, -1.5 })
foo(x);
}
打印:
tgamma of 1 = 1
tgamma of 2 = 1
tgamma of 3 = 2
tgamma of 4 = 6
tgamma of 5 = 24
tgamma of -0.2 = -5.82115
error at -2: "Error in function boost::math::tgamma<long double>(long double): Evaluation of tgamma at a negative integer -2."
tgamma of -0.5 = -3.54491
tgamma of -1.5 = 2.36327
它在 -2
溢出是可以理解的,但这是正确的。