Как справиться с переполнением поплавка? - PullRequest
3 голосов
/ 16 июля 2010

Если происходит переполнение значения, я хочу установить его на ноль, например так ...

m_speed += val;
if ( m_speed > numeric_limits<float>::max()) { // This might not even work, since some impls will wraparound after previous line
  m_speed = 0.f
}

, но как только val было добавлено к m_speed, переполнение уже произошло (и я предполагаю, что такая же проблема возникнет, если я if (( m_speed + val ) > ..).

Как я могу убедиться, что переполнение произойдет, не вызывая переполнение?

Ответы [ 2 ]

4 голосов
/ 16 июля 2010

Вы можете сделать:

if (numeric_limits<float>::max() - val < m_speed)
{
    m_speed = 0;
}
else
{
    m_speed += val;
}

Другим методом может быть:

m_speed += val;
if (m_speed == numeric_limits<float>::infinity())
    m_speed = 0;

Но имейте в виду, когда переполнение действительно происходит, результатом является неопределенное поведение.Таким образом, хотя это, вероятно, работает на большинстве машин, это не гарантируется.Лучше поймать его до того, как это произойдет.


Так как поначалу читать это не просто, я бы обернул его в функцию:

template <typename T>
bool will_overflow(const T& pX, const T& pValue, 
                    const T& pMax = std::numeric_limits<T>::max())
{
    return pMax - pValue < pX;
}

template <typename T>
bool will_underflow(const T& pX, const T& pValue, 
                    const T& pMin = std::numeric_limits<T>::min())
{
    return pMin + pValue > pX;
}

m_speed = will_overflow(m_speed, val) ? 0 : m_speed + val;
1 голос
/ 16 июля 2010

Если вы превысите FLT_MAX, тогда ваше значение с плавающей точкой станет INF, и вы можете проверить это явно, например,

#include <iostream>
#include <cfloat>
#include <cmath>

using namespace std;

int main(void)
{
    float f1 = FLT_MAX;
    float f2 = f1 * 1.001f;
    cout << "f1 = " << f1 << ", f2 = " << f2 << endl;
    cout << "isinf(f1) = " << isinf(f1) << ", isinf(f2) = " << isinf(f2) << endl;
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...