从C中的浮点获取指数

时间:2015-09-18 19:05:57

标签: c floating-point numbers exponent

我正在编写一个函数,它将获得浮点数(IEEE 754标准)的指数但由于某种原因,当我在数字上使用右移位运算符时,它返回0

这是函数

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

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

5 个答案:

答案 0 :(得分:7)

我猜你正在做某种投射hocus-pocus以将浮点传递为int s?我会使用float frexpf (float x, int* exp);中定义的<math.h>

#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或切换字符串,这会让您感到痛苦。

答案 1 :(得分: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

答案 2 :(得分: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

相同的结果

答案 3 :(得分:0)

主要问题是int而不是float并使用21 vs 23. @dbush

IEEE 754标准(binary32)有许多极端情况:Inifinty,NaN,sub-normal包括零。因此需要额外的代码来应对它们。

假设有适当的结尾:

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;
}

答案 4 :(得分:-1)

参数列表显示

int x

并传递浮点数。尝试用

代替
float x