Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing ints as floats

Suppose I have an API that only allows me to store floats, or arrays of floats. However, I would like to be storing integer values here.

I (roughly) understand that I am pretty okay with a straight cast up to around 2^23, but what if I want to go higher? Is there any way that I can take advantage of more of the 32 bits of a float and be sure I will get the same number back?


For clarification:

I'm doing some operations on point clouds with Pixar's PRMan (ie. RenderMan). I can write in either C or C++ linking against the precompiled point cloud API. PRMan at no point has to use these ints I am storing; I only need it to hand them back to me intact after operating on other data attached to the points.

like image 478
Mike Boers Avatar asked Nov 10 '10 23:11

Mike Boers


People also ask

Can int be stored in float?

So you cannot store a float value in an int object through simple assignment. You can store the bit pattern for a floating-point value in an int object if the int is at least as wide as the float , either by using memcpy or some kind of casting gymnastics (as other answers have shown).

Can we store int in float in Java?

float has 24 bits of precision (and a sign bit) which means you can store int values between -16777216 to 16777216 without loss of precision.

How do you store float value?

Scalars of type float are stored using four bytes (32-bits). The format used follows the IEEE-754 standard. The mantissa represents the actual binary digits of the floating-point number.

Can floats be ints?

Integers and floats are two different kinds of numerical data. An integer (more commonly called an int) is a number without a decimal point. A float is a floating-point number, which means it is a number that has a decimal place.


2 Answers

Questionable:

In C, you can do the following, which is potentially unsafe (due to strict-aliasing rules):

int i = XXX;
float f;
*(int *)&f = i;

and which relies on the assumption that sizeof(int) == sizeof(float).

Less questionable:

Safer, but more longwinded, is the following:

int i = XXX;
float f;
memcpy(&f, &i, sizeof(int));

This still relies on matching data-type sizes. However, both of the above make the assumption that the internals of the library you're using will do nothing at all to the data. For instance, it won't have any special handling for NaN, or +/-infinity, etc.

Safe:

Along an entirely different train of thought, if you're happy to waste two floats per int, you could do something like:

int i = XXX;
float f[2] = { (i & 0xFFFF), ((unsigned)i >> 16 };

This last one is safe (other than some pretty reasonable assumptions on the size of floats and ints).

like image 179
Oliver Charlesworth Avatar answered Oct 11 '22 08:10

Oliver Charlesworth


The mantissa field lets you store 23 bits. The exponent field lets you store almost 8 bits, it is 8 bits wide with a few values reserved. And there's a sign bit.

Avoiding the reserved values in the exponent, you can still store 31 bits of your choice.

You may find frexp and ldexp useful.

like image 27
Ben Voigt Avatar answered Oct 11 '22 08:10

Ben Voigt