Reputation: 199
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
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
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
Reputation: 1
&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
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
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
Reputation: 44250
float x = 43.133;
int y;
assert (sizeof x == sizeof y);
memcpy (&y, &x, sizeof x);
...
Upvotes: 6
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