最接近1.0的双倍是多少,那不是1.0吗?

有没有一种方法可以通过编程获得最接近1.0但实际上不是1.0的 double?

一种简单的方法是 memcpy 将这个 double 复制为一个相同大小的整数,然后减去一个。按照 IEEE754浮点格式的工作方式,这将最终导致指数减少1,同时将小数部分从所有零(1.00000000000)改为所有一(1.11111111111111111)。然而,存在一些机器,其中整数存储为 little-endian,而浮点数存储为 big-endian,因此这种方法并不总是有效。

6464 次浏览

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, 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.

In C++ you can also use this

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

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.