Название довольно понятно, ввод задан двойным значением, и я хочу добавить/вычесть наименьшую возможную сумму.
Как найти ближайшее следующее/предыдущее двойное значение (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 */