获取浮点数

时间:2016-01-01 18:04:03

标签: c floating-point unions

我找到了这段代码

#include <stdio.h>

union foo
{
    struct float_guts
    {
        unsigned int fraction : 23;
        unsigned int exponent : 8;
        unsigned int sign     : 1;
    } fg;
    float f;
};

void print_float(float f)
{
    union foo ff;
    ff.f = f;
    printf("%f: %d 0x%X 0x%X\n", f, ff.fg.sign, ff.fg.exponent, ff.fg.fraction);
}

int main(void)
{
    print_float(0.25);
    return 0;
}

节目输出:

0.250000: 0 0x7D 0x0

我试图理解为提取符号,尾数和指数,但到目前为止还不明白如何

有人可以向我解释一下吗?

3 个答案:

答案 0 :(得分:1)

  

获取浮点数的符号,尾数和指数

使用联合取决于知道float和endian-ness的格式,这不是由C定义的.OP的方法可能有些工作,它可能没有。如果使用IEEE 754 OP方法,则不考虑指数偏差,not-a-numbers,次正常数等等。

获得标志;

#include <stdbool.h>
#include <math.h>
bool sign = signbit(x);

将浮点数分解为标准化分数和 积分能力2:

#include <math.h>
int exponent;
float fraction; // [0.5f to 1.0)
fraction = frexpf(x, &exponent);

答案 1 :(得分:1)

首先,了解IEEE-754 单精度浮点格式是什么。简而言之,它是存储浮点数的二进制格式。对于 32位浮点数,它由单个符号位(1-negative),8位指数(超过127表示法)和23组成。位尾数/有效数(以隐藏位格式)。有无数的例子如何转换为IEE754符号或从IEE754符号转换,但足以说它是您的计算机用来存储浮点数的1 + 8 + 23 = 32-bit编码。例如,您0.25号码存储为:

(0.25 float - value in memory)
 0 0 1 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
|s|      exp      |                  mantissa                   |
十六进制格式的

's''exp''mantissa'

0  0x7d  0x0

union的整个问题与integer也是32-bit值的事实有关。因此,对于每个浮点值,都有一个等效的整数表示,它可以从上面相同的32位派生。 (这当然会带来你正在运行的硬件的 endianess 的问题,因为这些位将以不同的方式存储在内存中)

尽管如此,虽然注释和答案中的所有原因都不可取,但您可以在int(无符号)和float之间创建联合,这样您就可以满足自己关于内存中的位数。例如:

typedef union {
    float fv;
    unsigned int iv;
} ifu;

如果您随后创建了此union的实例并将0.25指定为浮点值,则它将存储在内存中,如上所示(假设为little-endian等等),例如:

ifu tmp;
tmp.fv = 0.25;

然后,您可以在内存中查看与float(您的0.25值)或等效无符号整数值相同的位。一个简单的printf %u0x%0x将为您提供:

1048576000   0x3e800000 (in hex)

这些位是完全相同的,你所做的只是查看位的不同解释 - 浮点数或整数。

简而言之,就是IEEE-754单精度浮点,符号位,指数,尾数,联合,无符号整数等价 - 问题。它远不止于此,但这将为您提供一个理解不同主题的框架。

答案 2 :(得分:0)

union使struct和float共享相同的内存空间。 代码写入float成员,然后读取union的另一个成员。它假设浮点数有23位尾数,8位指数和符号位,并打印出来。

NB工会用于节省内存空间,编写成员并阅读另一个成员是未定义的行为 - 它可能在某些系统上运行,或在其他系统上运行。 float映射也不是很便携。