这是我的代码。当我将尾数、指数和符号分别更改为 23、8 和 1 以表示 32 位数字时,我的代码可以正常工作。但是,当更改值以表示 16 位的比特率时,它不会返回正确的值。
#include <stdio.h>
#include <stdlib.h>
typedef union
{
float val;
struct
{
unsigned int mantissa: 10;
unsigned int exponent: 5;
unsigned int sign: 1;
}float16;
}IEEE_FP;
void print(unsigned int val, int num_bits)
{
for(int i = num_bits-1; i >= 0; i--)
{
if((val>>i)&1){printf("1");}
else{printf("0");}
}
}
void print16(IEEE_FP test)
{
print(test.float16.sign, 1);
print(test.float16.exponent, 5);
print(test.float16.mantissa, 10);
}
int main()
{
IEEE_FP test;
test.val = 0.789;
print16(test);
return EXIT_SUCCESS;
}
我尝试传递浮点数 0.789,并期望得到 0011101001010000,但是我的代码打印出 1111101111100111。有什么想法吗?
代码适用于 32 位
float
值的原因是,当值存储在联合的 float val
成员中时,它是使用 32 位 float
类型的表示来存储的。 (这种类型是 IEEE-754 二进制 32 格式,也称为“单精度”IEEE-754。)该表示形式是通过硬件和软件组合解析源代码中的 0.789
字符串并将其转换为二进制 32 格式来准备的.
联合之所以有效,是因为联合的
struct
成员中的位域使用与联合的 float val
成员相同的成员。使用位字段读取值会将这些位解释为整数,而不是将它们解释为二进制 32。然后,将这些值作为整数,您的程序可以打印它们。 (此外,位字段的布局方式很大程度上是实现定义的。C 标准允许位字段相对于内存中字节的顺序和对齐方式具有灵活性。因此此代码不可移植。)
当您将位域定义更改为 16 位浮点类型的宽度时,
float val
没有任何变化。二进制 32 的相同位仍在内存中。没有任何东西会自动将 float val
中的位更改为 16 位浮点类型的位,而不是二进制 32 的位。
要显示代表 16 位浮点类型值的位,您主要有两种选择:
float
中的float val
更改为16位浮点类型的名称。 C 标准没有指定这一点,但您的编译器可能有一个类型。有关这样做的更多信息取决于具体情况。如果这是学校作业,您应该使用之前课程中提供的信息。如果不是,那么如何继续取决于您尝试这样做的原因,是否需要快速或只是教育性的,是否需要可移植的或可以针对特定的 C 实现进行定制,等等。