0

我已经阅读了一些已经分解双打并“将它放在一起”的主题,但我试图将它分解成它的基本组件。到目前为止,我已经确定了一点:

breakDouble( double d ){

    long L = *(long*) &d;

    sign;
    long mask = 0x8000000000000000L;

    if( (L & mask) == mask ){

        sign = 1;

    } else {

        fps.sign = 0;
    }
    ...
}

但我对如何获得指数和尾数感到很困惑。我没有强迫双倍长,因为只有前导位很重要,所以截断没有发挥作用。但是,对于其他部分,我认为这不会起作用,而且我知道您不能对浮点数执行按位运算符,所以我被卡住了。

想法?


编辑:当然,一旦我发布了这个,我就会发现这个,但我不确定在这种情况下浮动和双打有多么不同。


编辑 2(对不起,我正在工作):我阅读了我在编辑 1 中链接的那篇文章,在我看来,我可以以同样的方式执行他们在我的双重上执行的操作,指数的掩码是:

mask = 0x7FF0000000000000L;

对于尾数:

mask = 0xFFFFFFFFFFFFFL;

这个对吗?

4

1 回答 1

4

您在第二次编辑中发布的位掩码看起来正确。但是,您应该知道:

  1. 像您这样取消引用(long *)&mydouble违反了 C 的别名规则。如果你传递一个像 gcc's 这样的标志,这仍然会在大多数编译器下-fno-strict-aliasing运行,但如果你不这样做,它可能会导致问题。您可以以这种方式投射char *并查看这些位。它更烦人,您必须担心字节顺序,但您不会冒编译器搞砸一切的风险。您还可以创建一个联合类型,如帖子底部的联合类型,并d在读取其他三个的同时写入成员。

  2. 较小的便携性说明: long不是所有地方的尺寸都一样;也许尝试使用 auint64_t代替?(double也不是,但很明显,这仅适用于 IEEE doubles。)

  3. 位掩码的诡计仅适用于所谓的“正常”浮点数——那些具有既不是零(表示次正规)或 2047(表示无穷大或 NaN)的偏置指数的那些。

  4. 正如 Raymond Chen 指出的那样,该frexp功能可以满足您的实际需要。 frexp以有记录且理智的方式处理次正规、无穷大和 NaN 情况,但您为使用它付出了速度。

(显然,列表和代码块之间需要一些非列表文本。就在这里;吃掉它,降价!)

union doublebits {
  double d;
  struct {
    unsigned long long mant : 52;
    unsigned int expo : 11;
    unsigned int sign : 1;
  };
};
于 2013-09-12T02:21:59.270 回答