很抱歉,如果已经有人问过这个问题,并且我已经看到了提取 float 指数的其他方法,但这就是给我的:
unsigned f2i(float f)
{
union {
unsigned i;
float f;
} x;
x.i = 0;
x.f = f;
return x.i;
}
我无法理解这个 union 数据类型,因为最后的返回 x.i 不应该总是使 f2i 返回 0 吗?
此外,这种数据类型对什么应用程序有用?例如,假设我有一个函数:
int getexponent(float f){
}
此函数应该获取偏差为 127 的 float 的指数值。我已经找到了很多方法来实现此目的,但是如何操作 f2i 函数来实现此目的?
非常感谢任何指点!
更新!! 哇,几年后,这看起来微不足道。 对于那些可能感兴趣的人,这是该功能!
int getexponent(float f) {
unsigned f2u(float f);
unsigned int ui = (f2u(f)>>23) & 0xff ;//shift over by 23 and compare to 0xff to get the exponent with the bias
int bias = 127;//initialized bias
if(ui == 0) return 1-bias; // special case 0
else if(ui == 255) return 11111111; //special case infinity
return ui - bias;
}
最佳答案
I'm having trouble understanding this union datatype
union 数据类型是程序员指示某个变量可以是多种不同类型之一的方法。 C11标准的措辞有点像“一个联盟最多包含一个成员”。它用于诸如逻辑上可能是这样或那样的参数之类的东西。例如,IP 地址可能是 IPv4 地址或 IPv6 地址,因此您可以按如下方式定义地址类型:
struct IpAddress
{
bool isIPv6;
union
{
uint8_t v4[4];
uint8_t v6[16];
} bytes;
}
你会这样使用它:
struct IpAddress address = // Something
if (address.isIPv6)
{
doSomeV6ThingWith(address.bytes.v6);
}
else
{
doSomeV4ThingWith(address.bytes.v4);
}
历史上,union
也被用来将一种类型的位转换为另一种类型的对象。这是因为,在 union 中,成员都从相同的内存地址开始。如果我这样做:
float f = 3.0;
int i = f;
编译器将插入代码将 float 转换为整数,因此指数将丢失。然而,在
union
{
unsigned int i;
float f;
} x;
x.f = 3.0;
int i = x.i;
i
现在包含表示 float
中的 3.0
的精确位。或者至少你希望如此。 C 标准中没有规定 float
和 unsigned int
必须具有相同的大小。 C 标准中也没有强制要求 float
的特定表示(嗯,附件 F 说浮点符合 IEC 60559 ,但我不知道这是否算作标准的一部分)。所以上面的代码充其量是不可移植的。
要获取float
的指数,可移植的方法是 frexpf() math.h
how could I manipulate the f2i function to serve this purpose?
让我们假设一个 float
以 32 位的 IEC 60559 格式存储,Wkipedia 认为它与 IEEE 754 相同。 。我们还假设整数以小端格式存储。
union
{
uint32_t i;
float f;
} x;
x.f = someFloat;
uint32_t bits = x.i;
bits
现在包含 float 的位模式。单精度 float 如下所示
SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
^ ^ ^
bit 31 bit 22 bit 0
其中S
是符号位,E
是指数位,M
是尾数位。
因此,获得 int32_t
后,您只需要进行一些移位和屏蔽:
uint32_t exponentWithBias = (bits >> 23) & 0xff;
关于c - 在c中获取 float 的指数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46339320/