简体   繁体   中英

In C89, how can I truncate and split a double precision floating point into two 32-bit words?

When targeting C99, I could truncate and split a double value into two 32-bit integers with the following code:

#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 however, does not seem to define a 64-bit integer type, so I can't use the compiler to perform the truncation. Even if the truncation was not necessary(the value already represented an integer) I also could not use bit operators like & or >> since these don't work on double values.

So, how can the above split() function be implemented in pure C89(and thus without relying on 64-bit integers), returning the 21/32 bit words that make up a 53-bit integer stored in a double value?

Ignoring the sign (as does the original code) it should be as simple as this:

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.);
}

To take negative numbers into consideration, operate on the absolute value then compute the two's complement:

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;
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM