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>?
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"));
}