Well I don't believe C++ has any real safe way to store floats without some sort of issue. When it comes to moving between machines and is both efficient and easily stored without using a large storage capacity.
It's very accurate, but it won't support really insane values. You will be able to have up to 7 digits in any location, but you can't exceed 7 digits on either side. For the left you'll receive inaccurate results. On the right you'll get an error during read time. To resolve the error you can throw an error during the write or perform "buffer[idx++] & 0x7" on the read to prevent it from going outside 0 and 7 bounds. Keep in mind "& 0x7" only works because it's a power of 2 minus one. Which is 2^3 - 1. You can only do that with those values E.g. 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, etc...
So it's up to you if you want to use this or not. I felt it was a safe way to get most values you'll ever need. The example below shows how it's converted into a 4 byte array, but for C++ this would be a char*. If you don't want to perform division you can convert the POWERS_OF_TEN array into a secondary array with decimals and multiple instead.
const float CacheReader::POWERS_OF_TEN[] =
{
1.0F, 10.0F, 100.0F, 1000.0F, 10000.0F, 100000.0F, 1000000.0F, 10000000.0F
};
float CacheReader::readFloat(void)
{
int flags = readUnsignedByte();
int value = readUnsignedTriByte();
if (flags & 0x1)
value = -value;
return value / POWERS_OF_TEN[(flags >> 1) & 0x7];
}
unsigned __int32 CacheReader::readUnsignedTriByte(void)
{
return (readUnsignedByte() << 16) | (readUnsignedByte() << 8) | (readUnsignedByte());
}
unsigned __int8 CacheReader::readUnsignedByte(void)
{
return buffer[reader_position] & 0xFF;
}
void CacheReader::writeFloat(float data)
{
int exponent = -1;
float ceiling = 0.0F;
for ( ; ++exponent < 8; )
{
ceiling = (POWERS_OF_TEN[exponent] * data);
if (ceiling == (int)ceiling)
break;
}
exponent = exponent << 0x1;
int ceil = (int)ceiling;
if (ceil < 0)
{
exponent |= 0x1;
ceil = -ceil;
}
buffer[writer_position++] = (signed __int16)(exponent);
buffer[writer_position++] = (signed __int16)(ceil >> 16);
buffer[writer_position++] = (signed __int16)(ceil >> 8);
buffer[writer_position++] = (signed __int16)(ceil);
}