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.
In c a value of 1 is an integer and 1.0 is a double, you use f after a decimal number to indicate that the compiler should treat it as a single precision floating point number.
Smallest DOUBLE value: -1.79769E+308. Largest DOUBLE value: 1.79769E+308. Smallest positive DOUBLE value: 2.225E-307. Largest negative DOUBLE value: -2.225E-307.
And the reason the comparison succeeds with 1.5 is that 1.5 can be represented exactly as a float and as a double ; it has a bunch of zeros in its low bits, so when the promotion adds zeros the result is the same as the double representation.
Instead when 1.0f is changed into 1.0 it becomes a double and thus 16777217 * 1.0 expression becomes a double (again because the standard dictates that in an expression with double and any other integral type, the result is a double ) which is large enough to hold the value 16777217 .
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With