最接近 1.0 的 double 不是 1.0 的是多少?

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

有没有办法以编程方式获取最接近 1.0 但实际上不是 1.0 的双精度值?

一个 hacky 方法是将双精度 memcpy 为相同大小的整数,然后减去一个。按照 IEEE754 浮点格式的工作方式,最终会将指数减一,同时将小数部分从全零 (1.000000000000) 更改为全一 (1.111111111111)。然而,存在整数以小端存储而浮点数以大端存储的机器,因此这并不总是有效。

自 C++11 起,您可以使用 nextafter 获取给定方向上的下一个可表示值:

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

Demo

在 C 中,你可以这样使用:

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

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

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

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

在 C++ 中你也可以使用这个

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

在 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 代替。