首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >boost::math:quadrature::sinh_sinh中的Bug?

boost::math:quadrature::sinh_sinh中的Bug?
EN

Stack Overflow用户
提问于 2019-06-02 14:30:20
回答 1查看 135关注 0票数 1

我在整个实行(-inf,inf)上搜索一个数字求积库,我找到了boost (版本1.70.0)。我想使用的函数是boost::math::quadrature:sinh_sinh。为了测试它,我从文档中复制了示例代码:

sinh.html

并想出了这样的代码:

代码语言:javascript
复制
#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“的第二个参数不是一个指向实数的指针,而是一个正常的实数。所以我不得不改变这句话:

代码语言:javascript
复制
double Q = integrator.integrate(f, &error, &L1);

进入这个世界:

代码语言:javascript
复制
double Q = integrator.integrate(f , boost::math::tools::root_epsilon<double>() , &error, &L1);

并取得了较好的效果。但我很好奇我能不能

代码语言:javascript
复制
double Q = integrator.integrate(f);

因为除了第一个之外,所有的集合都有默认值(因此,我对c++的理解是可选的)。不幸的是,这不能用Visual-Studio-2013编译。错误是:

错误C2783:"T boost::math::tools::root_epsilon(void)":模板-参数für "T“konnte nicht hergeleitet werden。(英文:它无法导出"T“的模板-参数)

发生在pathTo\boost_1_70_0\boost\math\quadrature\sinh_sinh.hpp的第33行

由于我不确定此错误是否仅与有关,所以我想问所有的人。

现在,我想在我感兴趣的函数上使用工作代码,即:

代码语言:javascript
复制
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而发生的?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-02 15:22:21

不幸的是,Visual对你不友好。在第二个例子中,我得到了更容易理解的错误消息:

代码语言:javascript
复制
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

我添加了一些诊断代码来帮助解决这个问题:

代码语言:javascript
复制
auto f = [](double x) {
    double y = pow(abs(x), 3) / cosh(x);
    if (!std::isfinite(y)) {
        std::cout << "f(" << x << ") = " << y << "\n";
    }
    return y;
};

我得到:

代码语言:javascript
复制
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

大多数人都很惊讶地得知,辛辛-辛正交在这么大的争论中评估了他们的功能。它也迫使他们去思考他们通常不需要考虑的事情,即:

IEEE算法不能接受极限。

例如,您可能知道作为$x \to \infty$,$x^2/(1+x^4) \to 0$。但是在IEEE浮点算法中,对于足够大的$x$,分子溢出和分母溢出,可以做些什么呢?唯一明智的解决方案就是使inf/inf成为nan。

在您的例子中,您知道cosh(x)的增长速度比pow(|x|, 3)快,但是IEEE没有。因此,您需要将限制行为的函数显式地告诉函数$x->\infty$ via:

代码语言:javascript
复制
#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;
}

最后一个注释:您的integrand是偶数,所以您可以在[0, inf]上使用[0, inf]求积并将结果加倍。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56415960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档