如何使用C中的常量将浮点转换为指数格式



所以我得到了

const int mask = 0x7F800000
const int shift = 23
const int bias = 127
int exp (float number)  {
unsigned int u = *(unsigned int*)&number;
int field = 0;

老实说,我只是困惑于如何正确格式化才能得到我想要的东西。本质上,客户端输入一个float,然后u是无符号int,它与float具有相同的位模式。

我知道我需要首先屏蔽除数字中的指数变量之外的所有内容。所以我认为是

field = (u & mask)

这应该会屏蔽位模式,除了我们想要的部分——指数。

然后第二步是把它移23,这样它就不会被所有的零包围。。。这就是我感到困惑的地方。

field = (u & mask) >> shift ???

看,我有点迷路了。也许这是对的。不管怎样,我们都在向右移动23。

最后一点就是要考虑到这种偏见。您希望返回实际的指数,而不是位。这样做的公式是指数位=(exp位模式(-偏置。。。所以我试试这个

field = ((u & mask) >> shift) - bias;
return(field);

我就是找不到正确的答案。首先,请放松我的格式设置。我是C的新手,这是一个初学者项目。我知道这不是很好。但是,有人能帮助我理解这些步骤的格式吗?或者帮我弥补我所缺少的?我只是想在逻辑上寻求帮助。

小心端序问题-对于类似IEEE-754的布局,我们可以有以下内容:

A        A+1      A+2      A+3        Big-endian addressing
+--------+--------+--------+--------+
|seeeeeee|efffffff|ffffffff|ffffffff|
+--------+--------+--------+--------+
A+3      A+2      A+1      A          Little-endian addressing

因此,在x86这样的小端系统上,您的值将被格式化为

+--------+--------+-------+--------+
|ffffffff|ffffffff|effffff|seeeeeee|
+--------+--------+-------+--------+

其中,第一个字节将是有效位的最低8位,然后是有效位中间的8位,接着是最低指数位,再接着是有效位最高的7位,再然后是符号位,再后面是指数最高的7个位。

此外,不能保证float值的比特模式将适合于unsigned int1。最好将浮点值视为unsigned char:的数组

union f32 {
float f;
unsigned char c[sizeof f];
};

您可以将您的价值分配给f成员:

union f32 myval = {.f = 1.234};

然后通过c成员进行检查

printf( "sign bit is %dn", (f32.c[3] & 0x80) >> 7 );

  1. unsigned int只需要存储中的值,至少范围[0..65535],这意味着它可以小到16位宽;在2000年之后构建的几乎任何系统上,它都将是32位宽的,但这并不是一个普遍正确的系统

三种方法:

  1. 最安全
int exp (float number)  {
unsigned int u;
memcpy(&u, &numberm sizeof(u));
  1. 在C中安全
int exp (float number)  {
union 
{
unsigned int u;
float f;
}fu = {.f = number};

然后你可以使用fu.u

  1. 不安全(指针敲击(
int exp (float number)  {
unsigned int *u = (void *)&number;

具有无符号值u

例如:

#define SIGN (1U << 31)
#define EXP  (0xff << 23)
unsigned sign = !!(u & SIGN)
unsigned exp = (u & EXP) >> 23;
unsigned mant = u & ~(SIGN | EXP);

最新更新