[英]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: 以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 however, does not seem to define a 64-bit integer type, so I can't use the compiler to perform the truncation. 但是C89似乎没有定义64位整数类型,因此我不能使用编译器执行截断。 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. 即使不需要截断(该值已经表示一个整数),我也无法使用
&
或>>
类的位运算符&
因为这些运算符不适用于double
值。
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? 那么,如何在纯C89中实现上面的
split()
函数(从而不依赖于64位整数),返回组成存储在double
值中的53位整数的21/32位字?
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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.