【问题标题】:How to handle a float overflow?如何处理浮动溢出?
【发布时间】:2023-03-04 01:23:01
【问题描述】:

如果一个值发生浮点溢出,我想将它设置为零,像这样......

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 ) &gt; ..) 也会出现同样的问题。

如何检查以确保将发生溢出而不导致溢出?

【问题讨论】:

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


    【解决方案1】:

    你可以这样做:

    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;
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • +/-Inf 与 NaN 不同
      • @Axel:好点 - 我不应该将两者混为一谈 - 我倾向于将 INF 视为一种 NaN,但 IEEE-754 将它们视为不同的实体。
      猜你喜欢
      • 1970-01-01
      • 2013-07-10
      • 2011-03-15
      • 2021-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多