在C89中,如何将双精度浮点截断并拆分为两个32位字?

时间:2016-02-29 13:16:36

标签: c c99 c89 ansi-c

在定位C99时,我可以使用以下代码截断并将double值拆分为两个32位整数:

#include <stdint.h>

void split(double d, unsigned long *most_significant_word, unsigned long *least_significant_word)
{
   uint64_t i = (uint64_t)d;
   *most_significant_word = i >> 32;
   *least_significant_word = i & 0xffffffff;
}
但是,C89似乎没有定义64位整数类型,所以我不能使用编译器来执行截断。即使截断不是必需的(值已经表示为整数),我也不能使用&>>之类的位运算符,因为它们不能处理double值。

那么,如何在纯C89中实现上述split()函数(因此不依赖于64位整数),返回组成存储在a中的53位整数的21/32位字。 double值?

1 个答案:

答案 0 :(得分:3)

忽略符号(与原始代码一样)它应该像这样简单:

void split(double d, unsigned long *most_significant_word, unsigned long *least_significant_word)
{
   *most_significant_word = d/4294967296.; // d>>32 in double
   *least_significant_word = fmod(d, 4294967296.);
}

要考虑负数,对绝对值进行操作,然后计算二进制补码:

void split(double d, unsigned long *most_significant_word, unsigned long *least_significant_word)
{
   double dabs = d < 0 ? -d : d;
   *most_significant_word = dabs/4294967296.;
   *least_significant_word = fmod(dabs, 4294967296.);
   if (d < 0) {
       *most_significant_word = ~*most_significant_word;
       *least_significant_word = ~*least_significant_word + 1;
       if (!*least_significant_word) *most_significant_word += 1;
   }
}