How to find nearest next/previous double value (numeric_limits::epsilon for given number)

后端 未结 4 1576
花落未央
花落未央 2020-12-14 19:07

The title is quite self-explanatory, input is given double value, and I want to add/substract the smallest amount possible.

相关标签:
4条回答
  • 2020-12-14 19:40

    How about:

    x += fabs(x) * std::numeric_limits<double>::epsilon();
    
    0 讨论(0)
  • 2020-12-14 19:43

    Here's a very dirty trick that isn't actually legal and only works if your platform uses IEEE754 floats: The binary representation of the float is ordered in the same way as the float value, so you can increment the binary representation:

    double x = 1.25;
    
    uint64_t * const p = reinterpret_cast<uint64_t*>(&x);
    
    ++*p;   // undefined behaviour! but it gets the next value
    
    // now x has the next value
    

    You can achieve the same effect entirely legally by doing the usual binary copy gymnastics to obtain a proper uint64_t value. Make sure to check for zero, infinity and NaN properly, too.

    0 讨论(0)
  • #define FLT_MIN         1.175494351e-38F        /* min positive value */
    #define FLT_MAX         3.402823466e+38F        /* max value */
    #define DBL_MIN         2.2250738585072014e-308 /* min positive value */
    #define DBL_MAX         1.7976931348623158e+308 /* max value */
    

    http://xona.com/2006/07/26.html

    0 讨论(0)
  • 2020-12-14 19:59

    If your compiler implements C99's math functions/C++11, you can use the nextafter:

    #include <cfloat> // DBL_MAX
    #include <cmath> // std::nextafter
    
    double x = 0.1;
    
    // next representable number after x in the direction of DBL_MAX
    double xPlusSmallest = std::nextafter(x, DBL_MAX); 
    

    Even if your compiler doesn't support it, it probably has an instrinsic for it. (MSVC has had _nextafter since 2005, for example. GCC probably implements it as standard.)

    If your compiler doesn't support it but Boost is available to you, you can do this:

    #include <boost/math/special_functions/next.hpp> // boost::float_next
    
    double x = 0.1;
    
    // next representable number after x
    double xPlusSmallest = boost::math::float_next(x); 
    

    Which is equivalent to this (emulating C99):

    #include <boost/math/special_functions/next.hpp> // boost::nextafter
    #include <cfloat> // DBL_MAX
    
    double x = 0.1;
    
    // next representable number after x in the direction of DBL_MAX
    double xPlusSmallest = boost::math::nextafter(x, DBL_MAX); 
    

    And if none of those work for you, you'll just have to crack open the Boost header and copy it.

    0 讨论(0)
提交回复
热议问题