如何确定两个任意a和b之间的唯一浮点数?

时间:2016-08-31 20:04:53

标签: floating-point double

我怎样才能编写一个通用的C例程num(a,b)来计算a和b之间的浮点数?假设a和b都是double类型。

例如,num(0,1e-17)应返回01e-17之间的双打数。

2 个答案:

答案 0 :(得分:7)

此答案假设“ab都属于double类型”double映射到IEEE 754双精度,以及它的表示形式,作为uint64_t整数访问,被解释为具有与浮点数相同的字节序。主流编译平台就是这种情况。

在这些假设下,正浮点数和负浮点数的表示是连续的64位整数。因此,为了计算相同符号的两个浮点数之间存在多少个数,计算它们的表示之间的整数数,将其解释为64位无符号整数:

double a, b;
…
uint64_t a1, b1;
memcpy(&a1, &a, 8);
memcpy(&b1, &b, 8);
int64_t d = a1 - b1;
if (d<0) d = -d;
d++; /* account for both a and b e.g. if a==b, they enclose one FP number */

如果浮点数不具有相同的符号,则计算负数和-0.0之间的浮点数,以及正数和{{之间的浮点数。 1}},使用上述方法。然后总结这两部分。

答案 1 :(得分:3)

@Pascal Cuoq很好地解释了double代表,endian等的模仿。

以下是如何提取double的序列号的变体。

unsigned long long SequenceNumber(double d) {
  assert(sizeof(double) == sizeof(uint64_t));
  union {
    double d;
    uint64_t u64;
    int64_t i64;
  } x = {d};
  uint64_t y;

  if (x.i64 < 0) {
    y = 0xFFFFFFFFFFFFFFFF - x.u64;
  } else {
    y = 0x8000000000000000 + x.u64;
  }
  return y;
}

unsigned long long SequenceDiff(double a, double b) {
  unsigned long long sna = SequenceNumber(a);
  unsigned long long snb = SequenceNumber(b);
  return sna > snb ? sna - snb : snb - sna;
}