Anonymous
Anonymous

Reputation: 199

Encoding int value as an IEEE-754 float (binary32)

Given the 32 bits that represent an IEEE 754 floating-point number, how can the number be converted to an integer, using integer or bit operations on the representation (rather than using a machine instruction or compiler operation to convert)?

I have the following function but it fails in some cases:

Input: int x (contains 32 bit single precision number in IEEE 754 format)

  if(x == 0) return x;

  unsigned int signBit = 0;
  unsigned int absX = (unsigned int)x;
  if (x < 0)
  {
      signBit = 0x80000000u;
      absX = (unsigned int)-x;
  }

  unsigned int exponent = 158;
  while ((absX & 0x80000000) == 0)
  {
      exponent--;
      absX <<= 1;
  }

  unsigned int mantissa = absX >> 8;

  unsigned int result = signBit | (exponent << 23) | (mantissa & 0x7fffff);
  printf("\nfor x: %x, result: %x",x,result);
  return result;

Upvotes: 19

Views: 49330

Answers (7)

user19750105
user19750105

Reputation: 1

Multiply float number a factor you want. In this case I multiplied with 100,000, because 5 decimals after fraction is have meaning in my operation.

Convert it to bytes and than join them and divide by 100,000 again.

double angleX, angleY;
angleX = 3.2342;
angleY = 1.34256;
printf("%f, %f", (double)angleX, (double)angleY);

int remain, j;
int TxData[8];
j=0;
remain=0;
unsigned long data = angleX*100000;
printf("\ndata : %d\n", data);

while(data>=256)
{
    remain= data%256;
    data = data/256;
    TxData[j]= remain;
    printf("\ntxData %d : %d", j, TxData[j]);
    j++;
}
TxData[j] = data;
printf("\ntxData %d : %d", j, TxData[j]);

int i=0;
long int angleSon=0;
for(i=0;i<=j;i++)
{

    angleSon += pow(256,i)*TxData[i]; 
    printf("\nangleSon : %li", angleSon);
}   

Upvotes: -1

Dino Dini
Dino Dini

Reputation: 463

// With the proviso that your compiler implementation uses
// the same number of bytes for an int as for a float:
// example float
float f = 1.234f;
// get address of float, cast as pointer to int, reference
int i = *((int *)&f);
// get address of int, cast as pointer to float, reference
float g = *((float *)&i);
printf("%f %f %08x\n",f,g,i);

Upvotes: 9

&x gives the address of x so has float* type.

(int*)&x cast that pointer to a pointer to int ie to a int* thing.

*(int*)&x dereference that pointer into an int value. It won't do what you believe on machines where int and float have different sizes.

And there could be endianness issues.

This solution was used in the fast inverse square root algorithm.

Upvotes: 22

Johan K&#246;hler
Johan K&#246;hler

Reputation: 59

You can cast the float using a reference. A cast like this should never generate any code.

C++

float f = 1.0f;
int i = (int &)f;
printf("Float %f is 0x%08x\n", f, i);

Output:

Float 1.000000 is 0x3f800000

If you want c++ style cast use a reinterpret_cast, like this.

int i = reinterpret_cast<int &>(f);

It does not work with expressions, you have to store it in a variable.

    int i_times_two;
    float f_times_two = f * 2.0f;
    i_times_two = (int &)f_times_two;

    i_times_two = (int &)(f * 2.0f);
main.cpp:25:13: error: C-style cast from rvalue to reference type 'int &'

Upvotes: 0

Carl
Carl

Reputation: 257

C has the "union" to handle this type of view of data:

typedef union {
  int i;
  float f;
 } u;
 u u1;
 u1.f = 45.6789;
 /* now u1.i refers to the int version of the float */
 printf("%d",u1.i);

Upvotes: 24

wildplasser
wildplasser

Reputation: 44250

float x = 43.133;
int y;

assert (sizeof x == sizeof y);
memcpy (&y, &x, sizeof x);
...

Upvotes: 6

Alex Brown
Alex Brown

Reputation: 42872

You cannot (meaningfully) convert a floating point number into an 'integer' (signed int or int) in this way.

It may end up having the integer type, but it's actually just an index into the encoding space of IEEE754, not a meaningful value in itself.

You might argue that an unsigned int serves dual purpose as a bit pattern and an integer value, but int does not.


Also there are platform issues with bit manipulation of signed ints.

Upvotes: -1

Related Questions