92
votes

Is there a way to programmatically get the double that is closest to 1.0, but isn't actually 1.0?

One hacky way to do this would be to memcpy the double to a same-sized integer, and then subtract one. The way IEEE754 floating-point formats work, this would end up decreasing the exponent by one while changing the fractional part from all zeros (1.000000000000) to all ones (1.111111111111). However there exist machines where integers are stored little-endian while floating-point is stored big-endian, so that won't always work.

4
You can't assume that +1 is the same distance (from 1.0) as -1. The interleaving of base 10 and base 2 floating point representations means that the gaps are uneven.Richard Critten
@Richard: you're right. It is very unlikely that subtracting one ULP will get the, er, "nextbefore" value, because I guess the exponent would have to be adjusted as well. nextafter() is the only proper way of achieving what he wants.Rudy Velthuis
FYI have a read of this blog (not mine): exploringbinary.com/…Richard Critten
@RudyVelthuis: It does work on every IEEE754 binary floating point format.Edgar Bonet
Ok, then tell me: what "does work on every IEEE754 floating point format"? It is simply not true that if you decrement the significand that you get the "firstbefore()" value, especially not for 1.0, which has a significand which is a power of two. That means that 1.0000... binary is decrement to 0.111111.... and to normalize it, you must shift it to the left: 1.11111... which requires you to decrement the exponent. And then you are 2 ulp away from 1.0. So no, subtracting one from the integral value does NOT give you what is asked here.Rudy Velthuis

4 Answers

150
votes

Since C++11, you may use nextafter to get next representable value in given direction:

std::nextafter(1., 0.); // 0.99999999999999989
std::nextafter(1., 2.); // 1.0000000000000002

Demo

24
votes

In C and C++, the following gives the closest value to 1.0:

#include <limits.h>

double closest_to_1 = 1.0 - DBL_EPSILON/FLT_RADIX;

Note however that in later versions of C++, limits.h is deprecated in favour of climits. But then, if you are using C++ specific code anyway, you can use

#include <limits>

typedef std::numeric_limits<double> lim_dbl;
double closest_to_1 = 1.0 - lim_dbl::epsilon()/lim_dbl::radix;

And as Jarod42 writes in his answer, since C99 or C++11 you can also use nextafter:

#include <math.h>

double closest_to_1 = nextafter(1.0, 0.0);

Of course in C++ you can (and for later C++ versions should) include cmath and use std::nextafter instead.

23
votes

In C, you can use this:

#include <float.h>
...
double value = 1.0+DBL_EPSILON;

DBL_EPSILON is the difference between 1 and the least value greater than 1 that is representable.

You'll need to print it to several digits in order to see the actual value.

On my platform, printf("%.16lf",1.0+DBL_EPSILON) gives 1.0000000000000002.

4
votes

In C++ you can also use this

1 + std::numeric_limits<double>::epsilon()