Как найти ближайшее следующее/предыдущее двойное значение (numeric_limits:: epsilon для заданного числа)

Название довольно понятно, ввод задан двойным значением, и я хочу добавить/вычесть наименьшую возможную сумму.

Ответ 1

Если ваш компилятор реализует математические функции C99/С++ 11, вы можете использовать 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); 

Даже если ваш компилятор не поддерживает его, он, вероятно, имеет для него неотъемлемый атрибут. (Например, MSVC имеет _nextafter с 2005 года. GCC, вероятно, реализует его как стандарт.)

Если ваш компилятор не поддерживает его, но Boost доступен для вас, вы можете сделать это:

#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); 

Что эквивалентно этому (эмуляция 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); 

И если ни один из них не работает для вас, вам просто нужно взломать заголовок Boost и скопировать его.

Ответ 2

Здесь очень грязный трюк, который на самом деле не является законным и работает только в том случае, если ваша платформа использует поплавки IEEE754: двоичное представление float упорядочено так же, как и значение float, поэтому вы можете увеличить двоичное представление:

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

Вы можете добиться такого же эффекта полностью на законных основаниях, выполнив обычную бинарную копию гимнастики, чтобы получить правильное значение uint64_t. Не забудьте также проверить нуль, бесконечность и NaN.

Ответ 3

Как насчет:

x += fabs(x) * std::numeric_limits<double>::epsilon();

Ответ 4

#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