c - 获取 float 的符号、尾数和指数

标签 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

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

谁能给我解释一下?

最佳答案

首先,了解什么是 IEEE-754 单精度 浮点格式。简单的说,就是存储 float 的二进制格式。对于32 位 float ,它由单个符号位(1 负数)、8 位指数(超过 127 表示法)和 23 -位尾数/有效数(隐藏位格式)。关于如何与 IEE754 表示法相互转换的示例数不胜数,但足以说明它是您的计算机用来存储 float 的 1 + 8 + 23 = 32 位 编码。例如,您的 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 位 值这一事实有关。因此,对于每个浮点值,都有一个等效的整数表示,可以从上面相同的 32 位导出。 (这当然会带来您正在运行的硬件的 endianess 问题,因为这些位将以不同的方式存储在内存中)

尽管如此,虽然由于评论和答案中的所有原因并不可取,但您可以在 int(unsigned) 和 float 之间创建 union ,这样您就可以满足你自己关于内存中的位。例如:

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

如果您随后创建此 union 的实例并将您的 0.25 分配为浮点值,它将存储在内存中,如上所示(假设小端等..)例如:

ifu tmp;
tmp.fv = 0.25;

然后您可以将内存中那些完全相同的位视为 float(您的 0.25 值)或等效的无符号整数值。带有 %u0x%0x 的简单 printf 将为您提供:

1048576000   0x3e800000 (in hex)

位是完全相同的,您所做的只是查看对位的不同解释——作为 float 或整数。

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

关于c - 获取 float 的符号、尾数和指数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34558621/

相关文章:

c++ - Win32 中机器内进程通信的最佳 IPC 方法是什么?

floating-point - 为什么不鼓励在 ClickHouse 表中使用浮点表示?

c - 如何使用包含结构的 union ?

c - 数组与 C 编程语言中的结构体和 union 有何不同?

更改指针时 C++ 指针中断

c - 如何将动态二维字符数组传递给 C 中的函数?

c - 从函数地址获取调用者函数名称

c - 嵌入式 C : Able to access some struct members but not others

math - 用初学者的话来说,NaN(不是数字)是什么?

c - 值 1.0e+1 的类型是什么