在归一化浮点数f之前(之前)的下一个归一化浮点数是多少?

pga*_*ast 6 floating-point

给定归一化的浮点数f,f 之后/之前的下一个归一化浮点数是多少.

随着比特twiddling,提取尾数和指数我有:

next_normalized(double&){
      if mantissa is not all ones
          maximally denormalize while maintaining equality 
          add 1 to mantissa
          normalize
      else 
          check overflow
          set mantissa to 1  
          add (mantissa size in bits) to exponent.
      endif
 }
Run Code Online (Sandbox Code Playgroud)

但是,这可以通过浮点运算来完成吗?

std::numeric_limits<double>::epsilon() 
Run Code Online (Sandbox Code Playgroud)

只是1的"邻域"中的误差差异 - 例如:

normalized(d+=std::numeric_limits<double>::epsilon()) = d for d large
Run Code Online (Sandbox Code Playgroud)

它看起来更像错误率而不是错误差异,因此我天真的直觉就是

(1.+std::numeric_limits<double>::epsilon())*f //should be the next.
Run Code Online (Sandbox Code Playgroud)

(1.-std::numeric_limits<double>::epsilon())*f //should be the previous.
Run Code Online (Sandbox Code Playgroud)

特别是我有3个问题,任何人都做了以下任何一个(对于IEEE754):

1)对这个问题做了错误分析?

2)证明(或可证明)对于任何标准化的双d

    (1.+std::numeric_limits<double>::epsilon())*d != d ?
Run Code Online (Sandbox Code Playgroud)

3)证明对于任何标准化的双数d,不存在双f

    d < f < (1.+std::numeric_limits<double>::epsilon())*d ? 
Run Code Online (Sandbox Code Playgroud)

Rob*_*ern 7

我不确定你的" 标准化双数" 是什么意思,但是在大多数C标准数学库中使用该函数来获得下一个可表示的双数.nextafter()


Ste*_*non 6

正如Robert Kern所说,你需要C nextafter()函数,或IEEE754 nextUp()和nextDown()函数,尽管这两个函数尚未广泛实现.

如果由于某种原因想要避免使用nextafter,你可以这样做:

double next = x + scalbn(1.0, ilogb(x) - 52);
Run Code Online (Sandbox Code Playgroud)

这将x ^的指数增加2 ^(指数x - 52),这恰好是最后一位(ULP)中的一个单位.

如果您没有常用的cmath函数:

double x = 1.0;
uint64_t rep;
assert(sizeof x == sizeof rep);
memcpy(&rep, &x, sizeof x);
rep += 1;
memcpy(&x, &rep, sizeof x);
Run Code Online (Sandbox Code Playgroud)

这通过对浮点值的按位表示进行操作,在x的有效数上加1; 如果下一个值在下一个binade中,这将进入指数,返回正确的值.如果你想让它适用于负值,你需要调整它.