除了无穷大和 NaN 之外,每个浮点数都可以精确地表示为两个整数的比率。一些双精度浮点数确实需要大于 64 位的整数——例如,1e-300
将转换为6032057205060441 / (2 ** 1049)
. 但是,近似范围内的浮点数(2**-40, 2**63)
可以无损地转换为两个 64 位整数的分数。
这种转换函数的一个例子是 Python 的as_integer_ratio()
浮点对象方法。从 Python/C-ese 翻译,代码如下所示:
#include <math.h>
#include <stdlib.h>
void double_as_ratio(double flt, long long *numerator, long long *denominator)
{
double float_part;
int exponent;
long long long_exponent;
int i;
float_part = frexp(flt, &exponent); /* flt == float_part * 2**exponent exactly */
for (i=0; i<300 && float_part != floor(float_part) ; i++) {
float_part *= 2.0;
exponent--;
}
/* flt == float_part * 2**exponent exactly and float_part is integral. */
*numerator = (long long) float_part; /* can overflow */
long_exponent = 1LL << labs((long) exponent); /* can overflow */
if (exponent > 0) {
*numerator *= long_exponent;
*denominator = 1;
}
else
*denominator = long_exponent;
}
此代码不依赖于位的确切布局,而仅依赖于C89 所需的frexp
和函数。floor
应用于浮点值,它会产生和0.1
的正确值。3602879701896397
36028797018963968