1

I am trying to use the boost::multiprecision library for floating (or in that case, fixed) point arithmetic. However, I am having trouble detecting potential overflow in the following way:

typedef boost::multiprecision::number<
                                      boost::multiprecision::cpp_dec_float<50>
                                     > flp_type;
typedef boost::multiprecision::number<
                                      boost::multiprecision::cpp_dec_float<100>
                                     > safe_flp_type;

flp_type _1 = std::numeric_limits<flp_type>::max();
flp_type _2("1");
flp_type _3 = std::numeric_limits<flp_type>::max();
flp_type dtNew;

// Here is the check
safe_flp_type _res = safe_flp_type(_1) + _2;

// **This condition is true for addition of _1 and _3,**
// but fails for _1 + _2
if(  (_res > std::numeric_limits<flp_type>::max())  // overflow
   ||(_res < std::numeric_limits<flp_type>::min())) // underflow
{
    BOOST_THROW_EXCEPTION(OverUnderflow() << SpecificErrInfo(L"Attempted floating point over/underflow"));
}

dtNew = _1 + _2;

Shouldn't even adding 1 to max() for the type trigger the throw of the exception? I have also checked the underlying type after the overflow, and it's not cpp_dec_float_inf, still cpp_dec_float_finite. Also, the value of dtNew is equal to std::numeric_limits::max()

Am I under a complete conceptual misapprehension here? If so, what would be the correct way to prevent a boost::multiprecision::cpp_dec_float<50> from overflowing?

4

1 回答 1

2

好的,我已经调试到库中,并且“错误”发生在这一行:

// Check if the operation is out of range, requiring special handling.
if(v.iszero() || (ofs_exp > max_delta_exp))
{
   // Result is *this unchanged since v is negligible compared to *this.
   return *this;
}

类型的 numeric_limit 加 1 可以忽略不计,所以加法被丢弃。因此它不是>=。

我的印象是该类型被实现为定点(我知道这个名字很愚蠢),但事实并非如此。这是来自boost doc

涉及 cpp_dec_float 的操作总是被截断。但是,请注意,由于它们实际上是保护数字,因此实际上这对大多数用例的准确性没有实际影响。

多精度库似乎没有固定精度类型,这真是令人遗憾。

但是,为了检查 cpp_dec_float 中的溢出,可以这样做:

dtNew = _1 * _2;
if(dtNew.backend().isinf())
{
    BOOST_THROW_EXCEPTION(OverUnderflow() << SpecificErrInfo(L"Attempted floating point over/underflow"));
}
于 2013-09-10T22:18:53.307 回答