将双精度浮点数转换为整数的指数和尾数

3

我试图从双精度数中提取尾数和指数部分。 对于测试数据'0.15625',期望的尾数和指数分别为'5'和'-5'(5*2^-5)。

double value = 0.15625; 
double mantissa  = frexp(value, &exp);

结果:尾数为0.625,指数为-2

在这里,返回的尾数是一个分数。对于我的用例(ASN.1编码),尾数应该是整数。我理解通过将尾数右移并调整指数,可以将二进制小数转换为整数。在此例中,0.625 base 100.101 base 2,因此需要3个字节进行移位以得到整数。但我发现很难找到通用算法。

所以我的问题是,如何计算要移动多少位才能将十进制小数转换为二进制整数?


我猜frexp不是你需要的,因为它返回一个标准化值-在范围[0.5, 1)(或相应的负范围)内。你能解释一下你实际上需要这两个整数值吗?也许简单的位提取更适合? - Adrian Mole
@Adrian,我的最终目标是将其编码为ASN.1 REAL格式。我想得到一个算法来将分数二进制转换为整数二进制。 - FaisalM
1
不断将“mantissa”乘以2,并从“exp”中减去1,直到“mantissa”具有等于整数值的值(或者,由于这是浮点数,请对该检查应用公差,即直到“mantissa”与整数值之间的差的绝对值小于您选择的公差)。 - Peter
1个回答

3
#include <cmath>        //  For frexp.
#include <iomanip>      //  For fixed and setprecision.
#include <iostream>     //  For cout.
#include <limits>       //  For properties of floating-point format.


int main(void)
{
    double value = 0.15625;

    //  Separate value into significand in [.5, 1) and exponent.
    int exponent;
    double significand = std::frexp(value, &exponent);

    //  Scale significand by number of digits in it, to produce an integer.
    significand = scalb(significand, std::numeric_limits<double>::digits);

    //  Adjust exponent to compensate for scaling.
    exponent -= std::numeric_limits<double>::digits;

    //  Set stream to print significand in full.
    std::cout << std::fixed << std::setprecision(0);

    //  Output triple with significand, base, and exponent.
    std::cout << "(" << significand << ", "
        << std::numeric_limits<double>::radix << ", " << exponent << ")\n";
}

示例输出:

(5629499534213120, 2, -55)

(如果值为零,出于美学考虑,您可能希望将指数强制为零。数学上,任何指数都是正确的。)


如果尾数是偶数,则可以将其除以二并调整指数以得到更小的表示形式。 - Goswin von Brederlow
@GoswinvonBrederlow:此代码和ASN.1规范并不假定浮点基数为二。 - Eric Postpischil
抱歉,我应该说如果“尾数 % 基数 == 0”,那么你可以除以“基数”。 - Goswin von Brederlow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接