3

I'm heaving an (big) array of floats, each float takes 4 bytes.

Is there a way, given the fact that my floats are ranged between 0 and 255, to store each float in less than 4 bytes?

I can do any amount of computation on the whole array.

I'm using C.

mskfisher
  • 3,291
  • 4
  • 35
  • 48
cojocar
  • 1,782
  • 2
  • 18
  • 22

3 Answers3

2

How much precision do you need?

You can store each float in 2 bytes by representing it as an unsigned short (ranges from 0 to 65,535) and dividing all values by 2^8 when you need the actual value. This is essentially the same as using a fixed point format instead of floating point.

Your precision is limited to 1.0 / (2^8) = 0.00390625 when you do this, however.

Chris Taylor
  • 46,912
  • 15
  • 110
  • 154
  • I don't know the precision for sure; I'll try this way, to see if it works. Anyway, thanks for the idea -- I could use 3 bytes, if I want more precision, but then I'll have some alignment issues. Maybe there is a solution without the loss of precision. – cojocar Feb 14 '12 at 09:35
  • 1
    As a sidenote, this is perfect for uniform distribution. If values tend to be around 0, where more precision is desired, you can use [half precision](http://en.wikipedia.org/wiki/Half-precision_floating-point_format) or a custom floating point with 3 bits for the exponent. – Lyth Feb 14 '12 at 09:39
1

The absolute range of your data doesn't really matter that much, it's the amount of precision you need. If you can get away with e.g. 6 digits of precision, then you only need as much storage as would be required to store the integers from 1-1000000, and that's 20 bits. So, supposing this, what you can do is:

1) Shift your data so that the smallest element has value 0. I.e. subtract a single value from every element. Record this shift.

2) Scale (multiply) your data by a number just large enough so that after truncation to an integer, you will not lose any precision you need.

3) Now this might be tricky unless you can pack your data into convenient 8- or 16-bit units--pack the data into successive unsigned integers. Each one of your data values needs 20 bits in this example, so value 1 takes up the first 20 bits of integer 1, value 2 takes up the remaining 12 bits of integer 1 and the first 8 bits of integer 2, and so on. In this hypothetical case you end up saving ~40%.

4) Now, 'decrypting'. Unpack the values (you have saved the # of bits in each one), un-scale, and un-shift.

So, this will do it, and might be faster and more compact than standard compression algorithms, as they aren't allowed to make assumptions about how much precision you need, but you are.

Matt Phillips
  • 9,465
  • 8
  • 44
  • 75
  • Thanks. Looks like the main idea is to figure out the precision first. – cojocar Feb 14 '12 at 09:40
  • 1
    Yes, that's the beginning and end of it I think. After that make sure that any 'bit packing' you do with *unsigned* integers, the sign bit can otherwise complicate things unnecessarily. Also, since your absolute range is limited and [floats only use 23 bits in the mantissa](http://en.wikipedia.org/wiki/File:IEEE_754_Single_Floating_Point_Format.svg) I think you are guaranteed at least *some* savings without any loss of precision through this kind of technique. – Matt Phillips Feb 14 '12 at 09:48
0

For example you could store integers (floats with .0) on one byte, but the other float need more bytes.

You could also use fixed-point if you don't worry about precision...

sinsedrix
  • 4,336
  • 4
  • 29
  • 53