2015-09-18 59 views
0

我正在写一个函数,会得到一个浮点数的指数(IEEE 754标准),但由于某些原因,当我使用右移位运算符的数量则返回0获取指数从浮点用C

下面是函数

int get_exp (int x) 
{ 
    return (((x >> 21) & 255) -127); 
} 

我传递7.23所以输出应该是2,由于某种原因(X >> 21)部分返回0时,它实际上应该返回129。 255是我使用掩模和(&)与浮点数的指数部分。

+1

邮编例如“我通过它7.23” – chux

+0

为什么在上面的代码右移通过'21',而不是由'23'位? – njuffa

回答

7

我猜你正在做某种铸造hocus-pocus来通过浮点数为int s?我将使用中定义的float frexpf (float x, int* exp);

#include <math.h> 

int get_exp(float x) 
{ 
    int exp; 
    frexpf(x, &exp); 
    return exp; 
} 

无论浮点类型的大小如何,它都可以工作。

如果你想自己滚吧,你能适应这个代码。

#define EXPONENT_BIAS (-127) 

int get_exp(float f) 
{ 
    int i; 
    union { 
     // Set here, then use s or c to extract 
     float f; 
     // This may or may not work for you 
     struct { 
      unsigned int sign: 1; 
      unsigned int exponent: 8; 
      unsigned int mantissa: 23; 
     } s; 
     // For debugging purposes 
     unsigned char c[sizeof(float)]; 
    } u; 

    // Assign, you might need to reverse the bytes! 
    u.f = f; 

    // You'll probably need this to figure out the field widths 
    for (i = 0; i < sizeof(float); i++) 
     fprintf(stderr, "%02x%s", u.c[i], (i + 1 < sizeof(float))? " ": "\n"); 

    // Just return the exponent 
    return (int)u.s.exponent + EXPONENT_BIAS; 
} 

这会咬你,如果sizeof(float) != 4,或者如果你切换字节顺序。

+0

我必须这样做,而不使用任何已定义的功能 –

+0

@Yimin Rong有没有办法做到这一点没有frexp? –

+0

@KareemYoussef - 添加了代码,但没有保证! –

-1

参数列表显示

int x 

,你传递一个浮点数。试着用

float x 
2

一个float是32位,并奠定了as specified here的假设下工作来代替,你有三个问题:

  • 你的函数需要接受一个float
  • 您需要将uint32_t指向float的地址,以便它看到相同的字节,然后针对解除引用的指针执行操作。
  • 该指数开始于第23位,而不是21,所以你必须通过21

#include <stdio.h> 
#include <stdint.h> 

int get_exp (float x) 
{ 
    uint32_t *i = (uint32_t *)&x; 
    return (((*i >> 23) & 255) -127); 
} 

int main() 
{ 
    printf("exp=%d\n",get_exp(7.23)); 
} 

结果转移:

exp=2 
+0

可以在不使用float数据类型的情况下完成吗? –

+1

@KareemYoussef它不能,否则有问题的数字将不会采用IEE 754浮点格式。除非你从一个字节数组手动构造它,也就是说。 – dbush

0

性能是否应不是问题,只需重复:

int expof(float f) { 
    int expo = 0; 
    if (f < 0.0) f = -f; 
    while (f < 0.5f) { 
    f *= 2.0f; 
    expo--; 
    } 
    while (f >= 1.0f) { 
    f *= 0.5f; 
    expo++; 
    } 
    return expo; 
} 

不依赖于任何特定float实现以外的指数在int适合。它不使用外部功能评论here

相同的结果,从int expo; frexpf(f, &expo); return expo

0

主要问题是int,而不是float的传球和使用21比23。@dbush

IEEE 754标准(binary32)有许多不同的情况:Inifinty,NaN,包括零的子正常。所以需要额外的代码来应对它们。

假设正确尾数:中

int get_exp(float x) { 
    assert(sizeof x == sizeof(uint32_t)); 
    union { 
    float x; 
    uint32_t u32; 
    } u = { x }; 
    #define EXPOSHIFT 23 
    #define EXPOMASK 255 
    #define EXPOBIAS 127 
    if (x == 0.0) return 0; 
    int expo = (int) (u.u32 >> EXPOSHIFT) & EXPOMASK; 
    if (expo == EXPOMASK) return INT_MAX; // x is infinity or NaN 
    if (expo == 0) return get_exp(x * (1L << EXPOSHIFT)) - EXPOSHIFT; 
    return expo - EXPOBIAS; 
}