Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 691
jorgbrown Avatar asked Aug 06 '16 07:08

jorgbrown


People also ask

Is 1.0 a double or float?

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.

What is the smallest double value?

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.

Is 1.5 a float or a double?

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.

What is the value of 1.0 F?

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 .


2 Answers

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

like image 77
Jarod42 Avatar answered Oct 24 '22 06:10

Jarod42


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.

like image 26
celtschk Avatar answered Oct 24 '22 08:10

celtschk