如何将ieee754双倍转换为两个整数的分数?

ant*_*tak 0 c floating-point

如何获得long long(64位)值abdouble(64位)值d,使得(double)a / b更多或更少的平等d?这可能吗(不会失去精确度)?

我已经尝试过这个但是它没有得到任何地方,所以我想也许我有错误的想法:

union ieee754_double u;
u.d = d;

long long a = (long long)u.ieee.mantissa0 << 32 | u.ieee.mantissa1;
long long b = (long long)1 << (u.ieee.exponent + IEEE754_DOUBLE_BIAS);
Run Code Online (Sandbox Code Playgroud)

use*_*342 5

除了无穷大和NaN之外,每个浮点数都可以精确地表示为两个整数的比率.一些双精度浮点数确实需要大于64位的整数 - 例如,1e-300将转换为6032057205060441 / (2 ** 1049).但是,近似范围内的浮点数(2**-40, 2**63)可以无损地转换为两个64位整数的一小部分.

这种转换函数的一个例子是Python的as_integer_ratio()float对象方法.从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;
}
Run Code Online (Sandbox Code Playgroud)

此代码不依赖于位的确切布局,而仅取决于C89所需的frexpfloor函数.应用于浮点值0.1,它生成正确的值360287970189639736028797018963968.