The title is quite self-explanatory, input is given double value, and I want to add/substract the smallest amount possible.
How about:
x += fabs(x) * std::numeric_limits<double>::epsilon();
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.
#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
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.