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

jor*_*own 86 c++ floating-point floating-accuracy

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

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

Jar*_*d42 138

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

std::nextafter(1., 0.); // 0.99999999999999989
std::nextafter(1., 2.); // 1.0000000000000002
Run Code Online (Sandbox Code Playgroud)

演示

  • 接下来的问题是"如何在stdlib中实现":P (41认同)
  • 在阅读@LightnessRacesinOrbit的评论后,我很好奇.[这就是glibc如何实现`nextafter`](http://bazaar.launchpad.net/~vcs-imports/glibc/master/view/head:/math/s_nextafter.c),[这就是musl如何实现它](https://git.musl-libc.org/cgit/musl/tree/src/math/nextafter.c)万一其他人想看看它是如何完成的.基本上:原始位杂乱无章. (14认同)
  • 这也是将double增加到下一个可表示整数的好方法:`std :: ceil(std :: nextafter(1.,std :: numeric_limits <double> :: max()))`. (10认同)
  • IMO,正确的做法是唯一能够做到这一点的方法.你可以做很多测试尝试,试图慢慢接近它,但这可能会很慢. (5认同)
  • @Cornstalks:我并不感到惊讶,因为它有点笨拙,唯一的其他选择是拥有 CPU 支持。 (3认同)

bar*_*nos 25

在C中,您可以使用:

#include <float.h>
...
double value = 1.0+DBL_EPSILON;
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 因此,除了`1.`为'1'000'000` [演示](http://ideone.com/xdeu9e)之外,其他一些值不会起作用 (10认同)
  • @ Jarod42:你是对的,但OP特别询问"1.0".顺便说一句,它也给出了最接近的值大于1,而不是绝对最接近的值1(可能小于1).所以我同意这是一个部分答案,但我认为它可能会有所贡献. (7认同)
  • 这不会给*最接近的*加倍到1.0,因为(假设基数2)在*1.0之前的双右*只是在*1.0之后的双右*的一半(这是你计算的那个). (6认同)

cel*_*chk 22

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

#include <limits.h>

double closest_to_1 = 1.0 - DBL_EPSILON/FLT_RADIX;
Run Code Online (Sandbox Code Playgroud)

但请注意,在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;
Run Code Online (Sandbox Code Playgroud)

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

#include <math.h>

double closest_to_1 = nextafter(1.0, 0.0);
Run Code Online (Sandbox Code Playgroud)

当然,在C++中,你可以(以及后来的C++版本)包含cmath和使用std::nextafter.