如何处理浮动溢出?

时间:2010-07-15 20:58:49

标签: c++ error-handling floating-point overflow

如果某个值出现浮动溢出,我想将其设置为零,就像这样...

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 个答案:

答案 0 :(得分:4)

你可以这样做:

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 :(得分:1)

如果超过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;
}