我已经阅读了一些已经分解过双打的主题,并且将它们放在一起"但我试图把它分解成它的基本组件。到目前为止,我已经确定了一点:
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;
这是对的吗?
答案 0 :(得分:4)
您在第二次编辑中发布的位掩码看起来正确。但是,你应该知道:
取消引用(long *)&mydouble
违反了C的别名规则。如果你传递像gcc -fno-strict-aliasing
这样的旗帜,这仍然会在大多数编译器下飞行,但如果你不这样做会导致问题。你可以转换为char *
并查看那些位。它更烦人,你不得不担心字节序,但你不会冒编译器搞砸一切的风险。您还可以创建一个类似于帖子底部的联合类型的联合类型,并在读取其他三个成员时写入d
成员。
次要便携性说明:long
各处都不一样;也许尝试使用uint64_t
代替? (double
也不是,但很明显,这只适用于IEEE double
。)
具有位掩码的技巧仅适用于所谓的“正常”浮点数 - 具有偏置指数既不为零(表示次正规)或2047(表示无穷大或NaN)的浮点数。
正如Raymond Chen指出的那样,frexp
函数可以完成你真正想要的功能。 frexp
以文档化和理智的方式处理次正规,无穷大和NaN情况,但是你使用它的速度很快。
(显然在列表和代码块之间需要有一些非列表文本。这就是它;吃掉它,降价!)
union doublebits {
double d;
struct {
unsigned long long mant : 52;
unsigned int expo : 11;
unsigned int sign : 1;
};
};