什么是1.0的最接近的两倍,那不是1.0?

时间:2016-08-06 07:52:37

标签: c++ floating-point floating-accuracy

有没有办法以编程方式获得最接近1.0的double,但实际上不是1.0?

执行此操作的一种hacky方法是将double传递给相同大小的整数,然后减去一个。 IEEE754浮点格式的工作方式,最终将指数减少一,同时将小数部分从全零(1.000000000000)更改为全1(1.111111111111)。但是,存在一些机器,其中整数存储为little-endian,而浮点存储为big-endian,因此并不总是有效。

4 个答案:

答案 0 :(得分:138)

从C ++ 11开始,您可以使用nextafter在给定方向上获得下一个可表示的值:

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

Demo

答案 1 :(得分:25)

在C中,您可以使用:

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

DBL_EPSILON是1和可表示的大于1的最小值之间的差异。

您需要将其打印成几位数才能看到实际值。

在我的平台上,printf("%.16lf",1.0+DBL_EPSILON)提供1.0000000000000002

答案 2 :(得分:22)

在C和C ++中,以下值给出了最接近1.0的值:

#include <limits.h>

double closest_to_1 = 1.0 - DBL_EPSILON/FLT_RADIX;

但请注意,在C ++的更高版本中,不推荐limits.h使用climits。但是,如果您仍在使用C ++特定代码,则可以使用

#include <limits>

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

正如Jarod42在他的回答中写道,自C99或C ++ 11以来你也可以使用nextafter

#include <math.h>

double closest_to_1 = nextafter(1.0, 0.0);

当然,在C ++中,您可以(以及以后的C ++版本)包含cmath并使用std::nextafter代替。

答案 3 :(得分:4)

在C ++中,您也可以使用此

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