在 C89 中,如何将双精度浮点截断并拆分为两个 32 位字?
In C89, how can I truncate and split a double precision floating point into two 32-bit words?
针对 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
值。
那么,上面的split()
函数如何在纯C89中实现(因此不依赖64位整数),返回构成存储的53位整数的21/32位字在 double
值中?
忽略符号(与原始代码一样)它应该像这样简单:
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;
}
}
针对 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
值。
那么,上面的split()
函数如何在纯C89中实现(因此不依赖64位整数),返回构成存储的53位整数的21/32位字在 double
值中?
忽略符号(与原始代码一样)它应该像这样简单:
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;
}
}