我正在搜索整个实数线(即(-inf,inf))上的数字正交库,我发现了boost(版本1.70.0)。我要使用的功能是boost :: math :: quadrature:sinh_sinh。为了测试它,我从文档中复制了示例代码:
并想到了以下代码:
#include <iostream>
#include <boost/math/quadrature/sinh_sinh.hpp>
using namespace boost::math::quadrature;
int main()
{
sinh_sinh<double> integrator;
auto f = [](double x) { return exp(-x*x); };
double error;
double L1;
double Q = integrator.integrate(f, &error, &L1);
std::cout << Q << "\t" << error << "\t" << L1 << std::endl;
int i = 0;
std::cin >> i; // Just to make sure the console does not close automatically
}
不幸的是,这不会编译,因为在文档中“ integrate”的第二个参数不是指向实数的指针,而是普通的实数。所以我不得不更改这一行:
double Q = integrator.integrate(f, &error, &L1);
进入这个:
double Q = integrator.integrate(f , boost::math::tools::root_epsilon<double>() , &error, &L1);
经过编译,结果良好。但是我很好奇我是否可以写
double Q = integrator.integrate(f);
因为除第一个以外的所有装饰都具有默认值(因此对于我对c ++的理解是可选的)。不幸的是,它将无法与Visual Studio-2013一起编译。错误是:
错误C2783:“ T boost :: math :: tools :: root_epsilon(void)”:template-Argumentfür“ T” konht nicht hergeleitet werden。 (用英语:它无法导出“ T”的模板参数)
在pathTo \ boost_1_70_0 \ boost \ math \ quadrature \ sinh_sinh.hpp的第33行
由于我不确定此错误是否仅与Visual Studio有关,所以我想问大家。
现在我想在感兴趣的功能上使用工作代码,即:
auto f = [](double x) {return pow(abs(x), 3) / cosh(x); };
此功能如下:
https://www.wolframalpha.com/input/?i=plot+abs(x)%5E3%2Fcosh(x)
,求和的结果应为约。 23.7:
https://www.wolframalpha.com/input/?i=integrate+abs(x)%5E3%2Fcosh(x)+from+-+inf+to+inf
该程序使用此功能进行编译,但会崩溃,即,我从Windows收到“程序已停止运行”消息。当我在调试模式下编译并运行它时,出现以下错误消息:
所以我的问题基本上是为什么boost :: math :: quadrature :: sinh_sinh无法集成此功能。对于正负无穷,它衰减到零,并且没有奇点。
是否所有这些错误都是由于我使用Visual Studio而发生的?
答案 0 :(得分:1)
不幸的是,Visual Studio对您不好。在您的第二个示例中,我得到了更清晰的错误消息:
terminate called after throwing an instance of 'boost::wrapexcept<boost::math::evaluation_error>'
what(): Error in function boost::math::quadrature::sinh_sinh<double>::integrate: The sinh_sinh quadrature evaluated your function at a singular point, leading to the value nan.
sinh_sinh quadrature cannot handle singularities in the domain.
If you are sure your function has no singularities, please submit a bug against boost.math
我添加了一些诊断代码来提供帮助:
auto f = [](double x) {
double y = pow(abs(x), 3) / cosh(x);
if (!std::isfinite(y)) {
std::cout << "f(" << x << ") = " << y << "\n";
}
return y;
};
我得到:
f(1.79769e+308) = nan
f(-1.79769e+308) = nan
f(2.01977e+137) = nan
f(-2.01977e+137) = nan
f(7.35294e+106) = nan
f(-7.35294e+106) = nan
大多数人惊讶地发现,sinh-sinh求积法以如此巨大的论据来评估其功能。这也迫使他们考虑通常不需要的事情,即:
IEEE算术不能取极限。
例如,您可能知道$ x \ to \ infty $,$ x ^ 2 /(1 + x ^ 4)\ to 0 $。但是在IEEE浮点算法中,对于足够大的$ x $,分子和分母都溢出了,怎么办?唯一明智的解决方案是只将inf / inf设为nan。
在您的情况下,您知道cosh(x)
的增长速度快于pow(|x|, 3)
,但IEEE却没有。因此,您需要通过以下方式将函数的限制行为明确地告知$ x-> \ infty $:
#include <iostream>
#include <cmath>
#include <boost/math/quadrature/sinh_sinh.hpp>
using namespace boost::math::quadrature;
int main()
{
sinh_sinh<double> integrator;
auto f = [](double x) {
double numerator = pow(abs(x), 3);
if (!std::isfinite(numerator)) {
return double(0);
}
return numerator / cosh(x);
};
double error;
double L1;
double tolerance = std::sqrt(std::numeric_limits<double>::epsilon());
double Q = integrator.integrate(f, tolerance, &error, &L1);
std::cout << Q << "\t" << error << "\t" << L1 << std::endl;
}
最后一条评论:您的被积是偶数,因此可以对exp_sinh
使用[0, inf]
求积,并将结果加倍。