Question

So I need to write a method to fulfill this puzzle:

float_f2i

  • Return bit-level equivalent of expression (int) f for floating point argument f.

  • Argument is passed as unsigned int, but it is to be interpreted as the bit-level representation of a single-precision floating point value.

  • Anything out of range (including NaN and infinity) should return 0x80000000u.

So what I took out of this is that I'm given a number in hex and I have to write code to put it in integer format. A test case given to us was; Argument [0x00800000], returns [0x0] because 0x00800000 is 1.1754....E-38, small enough to be returned as zero (So I am assuming)

What I have so far is:

int float_f2i(unsigned uf) {
  unsigned sign = uf & (0x80000000);
  unsigned exp  = uf >> 23 & 0xff;
  unsigned frac = uf & 0x7fffff;

  //takes care of NaN and inifinity
  if (exp == 255) {return 0x80000000u;}


  if ((exp > 0) && (exp < 255)) //normalized
  {
    if ((sign >> 28) == 0x0) //if sign bit is 0
    {
      return (0x1); //NEEDS MORE HERE
    }
    else if ((sign >> 28) == 0x8) //if sign bit is 1
    {
      return (0x8); //NEEDS MORE HERE
    }
  }
  else if (exp == 0)//denormalized
  {
    return 0; // rounds to zero anyway
  }
}

I know that for this to work I have to add on the exponential part to the return statements (1.frac^(exp-127)) but I have no idea how to code that in. Shifting to the left multiplies by two but for negative exponents of 2, I would need to shift right but the >> operator does that arithmetically. Do I need to create a dynamic mask to kill off the 1 bits created by arithmetic shifting?

EDIT: Got an answer and I was going the whole wrong direction, future reference if anyone has to do this:

int float_f2i(unsigned uf) {
  int exponent = (uf >> 23) & 0ff;
  int exp = exponent - 127;
  int frac = uf & 0x7fffff;

  if(exponent == 0x7F800000)
    return 0x80000000u;
  if(!exponent)
    return 0;
  if(exp < 0)
    return 0;
  if(exp > 30)
    return 0x80000000u;

  frac = frac | 0x800000;
  if (exp >= 23)
    frac = frac << (exp - 23);
  else
    frac = frac >> (23 - exp);

  if((uf >> 31) & 1)
    return ~frac + 1;

  return frac;
}
Was it helpful?

Solution

c only has one shift right operator >> but that is only an arithmetic shift when the number is a signed value type.

main()
{
  int x = -2;
  printf("%d\n",x>>1);
  printf("%d\n",((unsigned int)x)>>1);
  return 0;
}

Run it here

So you could cast to unsigned if you need to ensure non-arithmetic shift.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top