Precision and storing an unsigned 24 bit number in a float.

Based on my reading of the Wikipedia float page, and my own tests show that unsigned integers up to 16777216 (that is 2^24) are stored exactly in a float without being mangled in any way.

In my current project I have some classes that I use for storing and validating measurement data. Most of the data arrives as floating point values so I have used a float as the underlying data storage type. So far so good.

Now I’m pondering what to do with incoming integer and unsigned integer data. I very much doubt that I’ll ever have to store anything with 24 bits of precision so apart from the speed hit, would there be any disadvantage to using my existing float based classes for these values?

If I do go with this option is it safe to assume that Serial.print and anything else that knows about floats in the core Arduino libraries are going to correctly deal with values all the way up to 2^24 without getting creative and mangling the data?

I cannot say what would happen with your classes for validating the data because I cannot see the code.

By default, Serial.print only shows floats with two digits after the decimal point. This will mangle the output of some 24-bit floats unless further action is taken. I would suggest using long or unsigned long and classes intended for long or unsigned long. Perhaps a union would help?

Be aware that without a decimal point, floats are treated as signed integers so there's an almost implicit cast there. Also, I've just done some bitfield testing with float and union and the least 24 bits do not map to the integer value of the float. If you set the union to be a 24:8 struct and a float, set the float to 16777215 (2^24 -1), the float prints 16777215 (I don't use Serial.print) and the 24bit value prints 8388607 ((2^24 -1)/2).

DKWatson:
Be aware that without a decimal point, floats are treated as signed integers so there's an almost implicit cast there. Also, I've just done some bitfield testing with float and union and the least 24 bits do not map to the integer value of the float. If you set the union to be a 24:8 struct and a float, set the float to 16777215 (2^24 -1), the float prints 16777215 (I don't use Serial.print) and the 24bit value prints 8388607 ((2^24 -1)/2).

This sounds like it corresponds with the bit layout diagram on the Wikipedia page.

Looks like.