所以我得到了
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 int
1。最好将浮点值视为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 );
unsigned int
只需要存储中的值,至少范围[0..65535]
,这意味着它可以小到16位宽;在2000年之后构建的几乎任何系统上,它都将是32位宽的,但这并不是一个普遍正确的系统
三种方法:
- 最安全
int exp (float number) {
unsigned int u;
memcpy(&u, &numberm sizeof(u));
- 在C中安全
int exp (float number) {
union
{
unsigned int u;
float f;
}fu = {.f = number};
然后你可以使用fu.u
- 不安全(指针敲击(
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);