Какой ближайший двойной к 1.0, то есть 1.0?
Есть ли способ программно получить двойной, который ближе всего к 1.0, но на самом деле не 1.0?
Один взломанный способ сделать это - это memcpy double с целым числом одного и того же размера, а затем вычесть его. То, как работают форматы с плавающей запятой IEEE754, приведет к уменьшению экспоненты на единицу при изменении дробной части от всех нулей (1.000000000000) до всех (1.111111111111). Однако существуют машины, где целые числа хранятся мало-endian, в то время как с плавающей запятой сохраняется big-endian, поэтому это не всегда будет работать.
Ответы
Ответ 1
В C и С++ следующее дает самое близкое значение 1.0:
#include <limits.h>
double closest_to_1 = 1.0 - DBL_EPSILON/FLT_RADIX;
Обратите внимание, однако, что в более поздних версиях С++ limits.h
устарел в пользу climits
. Но тогда, если вы используете код С++ в любом случае, вы можете использовать
#include <limits>
typedef std::numeric_limits<double> lim_dbl;
double closest_to_1 = 1.0 - lim_dbl::epsilon()/lim_dbl::radix;
И как пишет Jarod42 в своем ответе, с C99 или С++ 11 вы также можете использовать nextafter
:
#include <math.h>
double closest_to_1 = nextafter(1.0, 0.0);
Конечно, на С++ вы можете (и для более поздних версий С++) включать cmath
и вместо этого использовать std::nextafter
.
Ответ 2
С С++ 11 вы можете использовать nextafter
, чтобы получить следующее представимое значение в заданном направлении:
std::nextafter(1., 0.); // 0.99999999999999989
std::nextafter(1., 2.); // 1.0000000000000002
Демо-версия
Ответ 3
В C вы можете использовать это:
#include <float.h>
...
double value = 1.0+DBL_EPSILON;
DBL_EPSILON
- это разница между 1 и наименьшим значением, превышающим 1, которое представляется.
Вам нужно распечатать его до нескольких цифр, чтобы увидеть фактическое значение.
На моей платформе printf("%.16lf",1.0+DBL_EPSILON)
дается 1.0000000000000002
.
Ответ 4
В С++ вы также можете использовать этот
1 + std::numeric_limits<double>::epsilon()