【问题标题】:Mysterious stackoverflow exception in boost::multiprecision::gmp_float::operator=?boost::multiprecision::gmp_float::operator= 中的神秘堆栈溢出异常?
【发布时间】:2019-10-08 07:06:10
【问题描述】:

我正在尝试使用Ramanujan's 公式计算我的一个大学项目的 pi,用于浮点后的任意位数。对于这项工作,我正在使用 boost::multiprecision 库,它只是我已经安装在我的机器上的 mpfr 和 mpir 的包装器。

到目前为止一切顺利,但我要么遗漏了什么,要么做错了什么,因为我的计算函数(计算公式中总和的每次迭代的函数)不时抛出 StackOverflow exception。 (启动时是一致的)

这就是它的样子

boost::multiprecision::mpf_float calculatePi(int start, int end)
{
    boost::multiprecision::mpf_float partition = 0;
    for (; start < end; ++start)
    {
        boost::multiprecision::mpf_float n = 
            factorial(4 * start) * boost::multiprecision::mpf_float(1103 + 26390 * start);
        boost::multiprecision::mpf_float d = 
            boost::multiprecision::pow(factorial(start), 4) * pow((boost::multiprecision::mpf_float)396, 4 * start); <-- this is where stackoverflow exception is thrown

        partition += (n / d);
    }

    return (2 * boost::multiprecision::sqrt((boost::multiprecision::mpf_float)2) / 9801) * partition;
}

我承认我对整个任意精度计算/转换和库太陌生了,所以我可能会遗漏一些东西。

我不能向你展示完整的调用堆栈,因为它太长了,但是在

之后
ParallelPi.exe!boost::multiprecision::number<boost::multiprecision::backends::gmp_float<0>,1>::**do_multiplies**<boost::multiprecision::detail::expression<boost::multiprecision::detail::function,boost::multiprecision::detail::number_kind_floating_pointpow_funct<boost::multiprecision::backends::gmp_float<0> >,boost::multiprecision::number<boost::multiprecision::backends::gmp_float<0>,1>,int,void>,boost::multiprecision::detail::function>(const boost::multiprecision::detail::expression<boost::multiprecision::detail::function,boost::multiprecision::detail::number_kind_floating_pointpow_funct<boost::multiprecision::backends::gmp_float<0> >,boost::multiprecision::number<boost::multiprecision::backends::gmp_float<0>,1>,int,void> & e, const boost::multiprecision::detail::function & __formal) Line 1754    C++

然后有 3603 后续调用

ParallelPi.exe!boost::multiprecision::number<boost::multiprecision::backends::gmp_float<0>,1>::**operator=**<boost::multiprecision::detail::function,boost::multiprecision::detail::number_kind_floating_pointpow_funct<boost::multiprecision::backends::gmp_float<0> >,boost::multiprecision::number<boost::multiprecision::backends::gmp_float<0>,1>,int,void>(const boost::multiprecision::detail::expression<boost::multiprecision::detail::function,boost::multiprecision::detail::number_kind_floating_pointpow_funct<boost::multiprecision::backends::gmp_float<0> >,boost::multiprecision::number<boost::multiprecision::backends::gmp_float<0>,1>,int,void> & e) Line 216  C++
ParallelPi.exe!boost::multiprecision::number<boost::multiprecision::backends::gmp_float<0>,1>::number<boost::multiprecision::backends::gmp_float<0>,1><boost::multiprecision::detail::function,boost::multiprecision::detail::number_kind_floating_pointpow_funct<boost::multiprecision::backends::gmp_float<0> >,boost::multiprecision::number<boost::multiprecision::backends::gmp_float<0>,1>,int,void>(const boost::multiprecision::detail::expression<boost::multiprecision::detail::function,boost::multiprecision::detail::number_kind_floating_pointpow_funct<boost::multiprecision::backends::gmp_float<0> >,boost::multiprecision::number<boost::multiprecision::backends::gmp_float<0>,1>,int,void> & e, void * __formal) Line 324   C++

只是在稍后的几个调用中导致stackoverflow异常

ParallelPi.exe!boost::multiprecision::backends::gmp_float<0>::precision() Line 630  C++

听起来很有趣,我不记得在“工作”之前更改了 calculatePi 函数。

你们能帮我弄清楚发生了什么,因为我似乎迷路了吗?

boost::multiprecision::mpf_float 的默认精度是浮点数之后的 150 位,这在以前不是问题(我记得我计算了一些具有 10 000 浮点精度的数字,而不是 SO 或其他)


请求

1.我的阶乘代码

boost::multiprecision::mpf_float factorial(int n)
{
    boost::multiprecision::mpf_float fact = 1;
    for (int i = 1; i <= n; ++i)
        fact *= i;

    return fact;
}

【问题讨论】:

  • 我没有答案,但是您可以通过重用某些术语来大大提高性能。 [(n+1)!]^4 = (n+1)^4 * (n!)^4396^[4(n+1)] = 394^4 * 396^(4n)150!^4 有超过 1000 位,394^(4n) 超过 1500。也许这会隐藏问题。
  • 我目前正在制作最愚蠢的解决方案,然后继续进行优化,不过,感谢您的建议,当我达到那一步时,我会记住它。关于数字溢出,我之前没有遇到过这个问题,而且当 start 为 0 时,这发生在循环的第一次迭代中。
  • @kuskmen:你对阶乘的定义在哪里?
  • 可能与您的问题无关,但我建议您使用 mpfr_float 而不是 mpf_float。它还有一个优点是它已经提供了 pi,因此您可以与您的结果进行比较。
  • @MarcGlisse 将 mpf_float 更改为 mpfr_float “修复”问题,现在我没有得到 SO 异常,但我想问题仍然悬而未决,为什么 mpf_float 会有 SO

标签: c++ boost gmp mpfr boost-multiprecision


【解决方案1】:

这是 Boost.Multiprecision 最新版本中的一个错误 - 我现在正试图解决这个问题,但请参阅 https://github.com/boostorg/multiprecision/issues/164

请注意,使用 mpfr 而不是 mpf 可以解决问题。

【讨论】:

    猜你喜欢
    • 2010-11-27
    • 1970-01-01
    • 2013-09-28
    • 1970-01-01
    • 2016-02-19
    • 2012-05-28
    • 1970-01-01
    相关资源
    最近更新 更多