C 获取浮点数的符号、尾数和指数
我找到了这个密码C 获取浮点数的符号、尾数和指数,c,floating-point,unions,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
#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;
}
我试图理解为提取符号、尾数和指数,但至今不明白如何理解
有人能给我解释一下吗?联合使结构和浮点共享相同的内存空间。 代码写入浮点成员,然后读取联合的另一个成员。它假设浮点有一个23位尾数,一个8位指数和一个符号位,然后打印它们 NB联合用于节省内存空间,写入一个成员和读取另一个成员是未定义的行为-它可能在某些系统上工作,也可能在其他系统上不工作。浮点映射也不是很好移植 获取浮点数的符号、尾数和指数 使用一个并集取决于知道浮点的格式和尾数,C.OP的方法中没有定义的东西可能会起作用,但可能不会。如果使用OPs方法,则会受到指数偏差、次正态数等因素的影响 获得标志
#include <stdbool.h>
#include <math.h>
bool sign = signbit(x);
#包括
#包括
布尔符号=符号位(x);
将浮点数分解为标准分数和
2的积分幂:
#include <math.h>
int exponent;
float fraction; // [0.5f to 1.0)
fraction = frexpf(x, &exponent);
#包括
整数指数;
浮点数;//[0.5f至1.0)
分数=frexpf(x,&指数);
首先,了解什么是IEEE-754单精度浮点格式。简单地说,它是存储浮点数的二进制格式。对于32位浮点数,它由一个单符号位(1负)、8位指数(超过127符号)和23位尾数/有效位(隐藏位格式)组成。关于如何转换为IEE754表示法或从IEE754表示法转换为IEE754表示法的例子不胜枚举,但只要说这是计算机用于存储浮点数的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'
和'尾数'
:
0 0x7d 0x0
联合
的整个问题与以下事实有关:整数
也是一个32位
值。因此,对于每个浮点值,都有一个等效的整数表示,可以从上面相同的32位派生。(这当然会带来您正在运行的硬件的持久性问题,因为这些位将以不同的方式存储在内存中)
尽管如此,由于注释和答案中的所有原因,不建议您在int
(无符号)和float
之间创建一个联合,这样您就可以满足内存中位的要求。例如:
typedef union {
float fv;
unsigned int iv;
} ifu;
如果您随后创建此联合的一个实例
,并将您的0.25
指定为浮点值,则它将存储在内存中,如上图所示(假设为小尾端等),例如:
然后,您可以将内存中的这些非常相同的位视为浮点值(您的0.25
值)或等效无符号整数值。使用%u
或0x%0x
的简单printf
将为您提供:
1048576000 0x3e800000 (in hex)
这些位是非常相同的,您所做的只是查看对这些位的不同解释——要么作为浮点,要么作为整数
简而言之,这就是IEEE-754单精度浮点、符号位、指数、尾数、并集、无符号整数等效问题。问题远不止于此,但这将为您理解不同主题提供一个框架。您希望得到什么输出?您实际得到什么输出?什么编译器,st您使用的是标准库和操作系统?这些标准库和操作系统的版本是什么?@Joachim Pileborg:代码运行得很好,我只是想了解它的工作原理。您期望什么?不要忘记尾数实际上是24位,因为MS位是一个隐含的1
(0值除外)。指数也有一个偏移量。请阅读您知道格式是如何工作的吗?并集和结构只是表示格式的另一种方式。@Kevin问题标题是否不正确?是否应该是“一个<代码>并集代码>如何工作?Hmmm“223位尾数”?(输入错误)。不同意“整数也是32位的”".OTOH,uint32\u t
始终为32位。同意这两个观点。根据问题的级别,我尝试调整答案的级别,以提供相关信息,而不会进一步模糊或使主要问题与附带细节复杂化。有时我获得了正确的平衡,有时会留下一些需要改进的地方。对于pu在这里,我应该补充一点,为了便于讨论,我们假设int为32位。合理的平台对浮点值和整数使用相同的endian值,因为这样做有好处。C没有定义的东西,实际上可以是位字段的布局。
ifu tmp;
tmp.fv = 0.25;
1048576000 0x3e800000 (in hex)