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

时间:2009-08-26 18:52:11

标签: floating-point

给定归一化的浮点数f,f之后/之前的下一个规范化浮点数是什么。

随着比特的蹒跚,提取尾数和指数我有:

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
 }

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

作为

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

只是1的“邻域”中的误差。 - 例如:

normalized(d+=std::numeric_limits<double>::epsilon()) = d for d large

它似乎更多的是错误率而不是错误差异,因此我天真的直觉是

(1.+std::numeric_limits<double>::epsilon())*f //should be the next.

并且

(1.-std::numeric_limits<double>::epsilon())*f //should be the previous.

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

1)对此问题进行了错误分析?

2)证明(或可以证明)任何标准化双d

    (1.+std::numeric_limits<double>::epsilon())*d != d ?

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

    d < f < (1.+std::numeric_limits<double>::epsilon())*d ? 

5 个答案:

答案 0 :(得分:7)

我不确定“规范化双倍数字”是什么意思,但是获得下一个可表示的双数字是在大多数nextafter() function完成的C标准数学库。

答案 1 :(得分:6)

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

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

double next = x + scalbn(1.0, ilogb(x) - 52);

这会将2 ^(指数x - 52)加到x,这恰好是最后一个位置(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);

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

答案 2 :(得分:3)

3)下的陈述是错误的。如果d略小于2,那么在d和(1 + eps)* d之间恰好有1个浮点数。这是一个展示它的程序:

#include <limits>
#include <iostream>

int main(int, char**)
{
  using namespace std;
  double d = 1.875;
  cout.precision(18);
  cout << "d = " << d << "\n";
  double d2 = (1.+numeric_limits<double>::epsilon())*d;
  cout << "d2 = " << d2 << "\n";
  double f = d + (d2-d)/2;
  cout << "f = " << f << "\n";
}

原因是(1 + eps)* 1.875等于1.875 + 1.875 * eps,其舍入为1.875 + 2 * eps。但是,1和2之间的连续浮点数之间的差异是eps,因此在1.875和1.875 + 2 * eps之间存在一个浮点数,即1.875 + eps。

我认为2)下的陈述是正确的。罗伯特克恩可能回答了你真正的问题。

答案 3 :(得分:1)

如下所述,经过一小部分研究后发现,对于大小为n比特的英特尔IEEE754格式的正浮动,&lt; + infinity将连接的指数和有效数视为一个n-1位无符号整数,加一个得到下一个更高和(减去一个得到下一个更低)

反之亦然,如果否定的话。特别地,可以将n-1位整数解释为表示独立于符号的绝对量值。因此,当负的浮点数f之后,负数必须减去1以使下一个浮点数接近零。

答案 4 :(得分:0)

1.0 - epsilon不是1.0的前身,所以负计数器部分根本不起作用...
1.0的前身是1.0-epsilon / 2.0