将双重分为符号,指数和尾数

时间:2013-09-12 02:04:39

标签: c double

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

breakDouble( double d ){

    long L = *(long*) &d;

    sign;
    long mask = 0x8000000000000000L;

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

        sign = 1;

    } else {

        fps.sign = 0;
    }
    ...
}

但我对如何获得指数和尾数感到非常难过。我离开时强迫双人进入一个长期,因为只有领先的位才重要,所以截断并没有发挥作用。然而,对于其他部分,我不认为这会起作用,我知道你不能在浮点数上做位操作符,所以我被卡住了。

思想?


编辑:当然,我发布此内容后发现this, but I'm not sure how different floats and doubles are in this case.


编辑2(抱歉我正常工作):我读过我在编辑1中链接过的帖子,在我看来,我可以用同样的方式执行他们正在做的操作,用指数掩码:

mask = 0x7FF0000000000000L;

和尾数:

mask = 0xFFFFFFFFFFFFFL;

这是对的吗?

1 个答案:

答案 0 :(得分:4)

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

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

  2. 次要便携性说明:long各处都不一样;也许尝试使用uint64_t代替? (double也不是,但很明显,这只适用于IEEE double。)

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

  4. 正如Raymond Chen指出的那样,frexp函数可以完成你真正想要的功能。 frexp以文档化和理智的方式处理次正规,无穷大和NaN情况,但是你使用它的速度很快。

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

    union doublebits {
      double d;
      struct {
        unsigned long long mant : 52;
        unsigned int expo : 11;
        unsigned int sign : 1;
      };
    };