# compressing my [0,1] floats by throwing away the integer part

I am compressing a string of data in the formats of float. The current approach is throwing away eight bits in the integer part as my float is strictly within [0,1].

I wonder how I could do this.

• Are you talking about IEEE floats? If the numbers are [0,1], then there are no integer bits per se. You could get rid of the sign bit, as that'd be constant, but it's not much of a saving. Commented Oct 27, 2022 at 7:57
• For [0,1] values an easier approach to compression is to convert it to a fixed-point representation with however many bits you want (8 or 16, for example). Commented Oct 27, 2022 at 17:37

In GLSL use frac to get the fractional part:

   float x=1.02;
x = frac(x);  // x==0.02 (in C++ use the modf function)


Multiply the fractional part by the max of the accuracy you want:

  float accuracy=255;  // 8 bits of accuracy (65535 for 16 bits)
x*=255;  // x==5.12


Throw away the fractional part:

  int y = round(x);  // y == 5;


The value is ready to be stored in whatever 8 bit format is need. Such as a texture, or vertex attributes, etc.

To recover the fraction:

float x = (float)value / 255.0;  // 5.0/255.0 == 0.01953125


This gives unsigned values between 0 and 1. A similar approach can be used for values between -1 and 1.

Precision is lost to the 8 bit encoding. But like mentioned in the comments that same can be done with 16 bit numbers.

If the values need to be stored in a texture then there are image formats just for this such as UNORM and SNORM. The GPU does the math for these formats when they are read from the texture.

The specs for the different API's provide guidelines on the expected values. The vulkan spec has something close to a function and a good explanation of the conversions it expects.

• Small nitpick, when converting to int you should use round() or similar, rather than a simple cast which truncates. Commented Oct 29, 2022 at 19:03