проверка переполнения boost::multiprecision::cpp_dec_float_50

Я пытаюсь использовать библиотеку boost::multiprecision для арифметики с плавающей (или в этом случае фиксированной) точкой. Однако у меня возникают проблемы с обнаружением потенциального переполнения следующим образом:

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;

Не должно ли даже добавление 1 к max() для типа вызывать исключение? Я также проверил базовый тип после переполнения, и это не cpp_dec_float_inf, а cpp_dec_float_finite. Кроме того, значение dtNew равно std::numeric_limits::max().

Я здесь в полном концептуальном заблуждении? Если да, то как правильно предотвратить переполнение boost::multiprecision::cpp_dec_float‹50>?


person namezero    schedule 10.09.2013    source источник


Ответы (1)


Хорошо, я отладил библиотеку, и в этой строке происходит «ошибка»:

// 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;
}

Добавление 1 к numeric_limit типа незначительно, поэтому добавление отбрасывается. Следовательно, это не >=.

У меня сложилось впечатление, что тип был реализован как фиксированная точка (тупой, учитывая имя, я знаю), что это не так. Это из повышения документ

Операции с участием cpp_dec_float всегда усекаются. Однако обратите внимание, что, поскольку они являются защитными цифрами, на практике это не оказывает реального влияния на точность в большинстве случаев использования.

Облом, что библиотека с высокой точностью, похоже, не имеет фиксированного типа точности.

Однако, чтобы проверить наличие переполнения в cpp_dec_float, можно сделать так:

dtNew = _1 * _2;
if(dtNew.backend().isinf())
{
    BOOST_THROW_EXCEPTION(OverUnderflow() << SpecificErrInfo(L"Attempted floating point over/underflow"));
}
person namezero    schedule 10.09.2013