Переполнение double (fetestexcept)

Я не могу понять почему нельзя получить ошибку переполнения при сложении или вычитании.

//Код работает
    std::feclearexcept (FE_ALL_EXCEPT);
    double a = std::numeric_limits<double>::max() * 2;
    int flag = std::fetestexcept(FE_OVERFLOW);
    if(flag)
        std::cout << "Overflow" << std::endl;



 //Код не работает
    std::feclearexcept (FE_ALL_EXCEPT);
    double a = std::numeric_limits<double>::max() + 2;
    int flag = std::fetestexcept(FE_OVERFLOW);
    if(flag)
        std::cout << "Overflow" << std::endl;

Что не правильно? Есть ещё способ отследить переполнение при сложении?


Ответы (1 шт):

Автор решения: user7860670

Тут на самом деле несколько проблем:

  1. Числа с плавающей точкой не могут представлять целые числа без потерь выше какой-то разрядности (53 бит в случае с double), соответственно операции с такими числами могут считаться операциями с потерей точности, а не с переполнением. Так правильнее будут проверять вот так:
int flag = std::fetestexcept(FE_ALL_EXCEPT);
if(not flag)
{
    std::cout << "OK" << std::endl;
}
else
{
    if(FE_INEXACT bitand flag)
    {
        std::cout << "FE_INEXACT" << std::endl;
    }
    if(FE_INVALID bitand flag)
    {
        std::cout << "FE_INVALID" << std::endl;
    }
    if(FE_OVERFLOW bitand flag)
    {
        std::cout << "FE_OVERFLOW" << std::endl;
    }
    if(FE_UNDERFLOW bitand flag)
    {
        std::cout << "FE_UNDERFLOW" << std::endl;
    }
}

FE_INEXACT

  1. Для увеличение производительности многие компиляторы в режиме по-умолчанию не генерируют код для отлавливания всех исключений для операций с числами с плавающей точкой. Соответственно чтобы этот код заработал, необходимо указывать дополнительные параметры, -frounding-math для gcc, /fp:strict для vc.

online compiler

→ Ссылка