What's the closest double to 1.0, that isn't 1.0?

C++Floating PointFloating Accuracy

C++ Problem Overview


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.

C++ Solutions


Solution 1 - C++

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

Solution 2 - C++

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.

Solution 3 - C++

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.

Solution 4 - C++

In C++ you can also use this

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjorgbrownView Question on Stackoverflow
Solution 1 - C++Jarod42View Answer on Stackoverflow
Solution 2 - C++celtschkView Answer on Stackoverflow
Solution 3 - C++barak manosView Answer on Stackoverflow
Solution 4 - C++phuclvView Answer on Stackoverflow