有没有办法以编程方式获取最接近1.0的double,但实际上不是1.0?
一种可行的方法是将双精度数存为相同大小的整数,然后减去一个。IEEE754浮点格式的工作方式是,将小数部分从全零(1.000000000000)更改为全1(1.111111111111),最终将指数减小了一个。但是,有些机器将整数存储在低位在前,而浮点存储在大在前,因此这并不总是可行。
有没有办法以编程方式获取最接近1.0的double,但实际上不是1.0?
一种可行的方法是将双精度数存为相同大小的整数,然后减去一个。IEEE754浮点格式的工作方式是,将小数部分从全零(1.000000000000)更改为全1(1.111111111111),最终将指数减小了一个。但是,有些机器将整数存储在低位在前,而浮点存储在大在前,因此这并不总是可行。
nextafter()
是实现他想要的唯一正确方法。
1.0000...
二进制要递减0.111111....
并标准化,您必须将其向左移动:1.11111...
这要求您递减指数。然后您距1.0仅有2 ulp。因此,不,从积分值中减去1不会给您这里的要求。
Answers:
在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
。
std::ceil(std::nextafter(1., std::numeric_limits<double>::max()))
。
nextafter
,这也是musl的实现方式,以防其他人想知道它是如何完成的。基本上是:原始位旋转。
在C中,您可以使用以下命令:
#include <float.h>
...
double value = 1.0+DBL_EPSILON;
DBL_EPSILON
是1与可表示的最小值之间的差,大于1。
您需要将其打印为几位数字才能查看实际值。
在我的平台上,printf("%.16lf",1.0+DBL_EPSILON)
给出1.0000000000000002
。
1.0
。顺便说一句,它也给出最接近的值大于1,而不是绝对最接近的值1(可能小于1)。因此,我同意这是部分答案,但我认为它仍然可以有所作为。