繁体   English   中英

为什么Boost多精度不能与Boost有理数库一起使用?

[英]Why does Boost multiprecision not work with Boost rational number library?

我正在将Boost 1.55.0与clang 3.5.0和gcc 4.8.1一起使用。

现在,我想计算最多256个阶乘(无精度损失):

#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>

int main(){
    using boost::multiprecision::uint128_t;    
    using boost::rational;
    using std::cout;
    using std::endl;

    typedef unsigned long long unsigned_int;
//    typedef uint128_t unsigned_int;    

    rational<unsigned_int> r((unsigned_int)1,

//((unsigned_int)1)<<127);
~(((unsigned_int)-1)>>1));

    unsigned_int n_I = 1;
    cout << "0!:\t\t" << r << endl;
    cout << "1!:\t\t" << r << endl;
    for(unsigned_int i=2; i<257; ++i){
        r *= i;
        cout << i << "!:\t\t" << r << endl;
    }

    return 0;
}

旁注:大阶乘在二进制表示形式中有许多尾随零,因此我从值为1 /(2 ^ 127)的有理变量开始。 这将自动使分子尽可能小。

我的问题:它不与工作uint128_t从升压多倍! 但它确实适用于unsigned long long

这是我的终端输出:

~/ccpp_projects/facultiy $ clang++ -I /usr/local/include/boost-1_55 faculty.cpp -o faculty
In file included from faculty.cpp:51:
In file included from /usr/local/include/boost-1_55/boost/multiprecision/cpp_int.hpp:12:
In file included from /usr/local/include/boost-1_55/boost/multiprecision/number.hpp:22:
In file included from /usr/local/include/boost-1_55/boost/multiprecision/detail/generic_interconvert.hpp:9:
In file included from /usr/local/include/boost-1_55/boost/multiprecision/detail/default_ops.hpp:2073:
/usr/local/include/boost-1_55/boost/multiprecision/detail/no_et_ops.hpp:25:4: error: implicit instantiation of undefined template
      'boost::STATIC_ASSERTION_FAILURE<false>'
   BOOST_STATIC_ASSERT_MSG(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
   ^
/usr/local/include/boost-1_55/boost/static_assert.hpp:36:48: note: expanded from macro 'BOOST_STATIC_ASSERT_MSG'
#     define BOOST_STATIC_ASSERT_MSG( B, Msg ) BOOST_STATIC_ASSERT( B )
                                               ^
/usr/local/include/boost-1_55/boost/static_assert.hpp:169:13: note: expanded from macro 'BOOST_STATIC_ASSERT'
            sizeof(::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL_CAST( __VA_ARGS__ ) >)>\
            ^
/usr/local/include/boost-1_55/boost/rational.hpp:533:15: note: in instantiation of function template specialization
      'boost::multiprecision::operator-<boost::multiprecision::backends::cpp_int_backend<128, 128, 0, 0, void> >' requested here
        num = -num;
              ^
/usr/local/include/boost-1_55/boost/rational.hpp:139:61: note: in instantiation of member function
      'boost::rational<boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<128, 128, 0, 0, void>, 0> >::normalize' requested here
    rational(param_type n, param_type d) : num(n), den(d) { normalize(); }
                                                            ^
faculty.cpp:63:28: note: in instantiation of member function 'boost::rational<boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<128, 128,
      0, 0, void>, 0> >::rational' requested here
    rational<unsigned_int> r((unsigned_int)1, ~(((unsigned_int)-1)>>1));
                           ^
/usr/local/include/boost-1_55/boost/static_assert.hpp:87:26: note: template is declared here
template <bool x> struct STATIC_ASSERTION_FAILURE;
                         ^
1 error generated.

附录

我只是用g ++编译了代码,就可以在那工作了! 有什么方法可以禁用clang ++的BOOST STATIC ASSERT吗?

normalize()的实现假定翻转基础整数类型的符号( i = -i )是已定义的操作。

unsigned long long就是这种情况,而uint128_t 不是

Yould

  1. 使用cpp_rational (请参阅Live On Coliru上的内容

  2. 手动分解出2的幂: Live On Coliru ,输出:

     0!: 1 1!: 1 2!: 1 x 2^1 3!: 3 x 2^1 4!: 3 x 2^3 ... 255!: 62542083004847430224885350954338565259 x 2^247 256!: 62542083004847430224885350954338565259 x 2^255 

首先可能是您想要的吗? 它将更加高效,并防止128位溢出。

#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>

int main(){
    using boost::multiprecision::uint128_t;

    uint128_t mantissa = 1;
    unsigned int binary_exponent = 0;

    std::cout << "0!:\t\t" << mantissa << std::endl;
    std::cout << "1!:\t\t" << mantissa << std::endl;

    for(unsigned i=2; i<257; ++i){
        unsigned tmp = i;
        while (tmp && ((tmp % 2) == 0))
        {
            binary_exponent += 1;
            tmp             /= 2;
        }
        mantissa *= tmp;
        std::cout << i << "!:\t\t" << mantissa << " x 2^" << binary_exponent << std::endl;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM