Вы потеряете точность.
// a, b, b in the range of -127.5 +127.5
uint32_t Code(float a, float b, float c)
{
union
{
uint32_t u32;
uint8_t u8[4];
} u;
u.u8[3] = 0xff;
u.u8[0] = a + 127.5f;
u.u8[1] = b + 127.5f;
u.u8[2] = c + 127.5f;
return u.u32;
}
void DeCode(uint32_t u32, float *a, float *b, float *c)
{
union
{
uint32_t u32;
uint8_t u8[4];
} u;
u.u32 = u32;
*a = (float)u.u8[0] - 127.5f;
*b = (float)u.u8[1] - 127.5f;
*c = (float)u.u8[2] - 127.5f;
}
int main(void)
{
float a = 102.3f, b = -56.4f, c = -126f, d,e,f;
uint32_t coded = Code(a, b, c);
DeCode(coded, &d, &e, &f);
printf("Original values: %f,%f,%f. Coded -%x. Decoded %f,%f,%f\n", a, b, c, coded, d, e, f);
}
Для большей точности вы можете масштабировать ее до 10 бит.
#define B10MAX ((float)((1u << 10) - 1))
float Scale(float x)
{
return B10MAX * (x + 127.5f) / 255.0f;
}
float DeScale(unsigned x)
{
return 255.0f *(x) / B10MAX - 127.5f;
}
uint32_t Code10(float a, float b, float c)
{
union
{
uint32_t u32;
struct
{
uint32_t value1 : 10;
uint32_t value2 : 10;
uint32_t value3 : 10;
};
} u;
u.value1 = Scale(a);
u.value2 = Scale(b);
u.value3 = Scale(c);
return u.u32;
}
void DeCode10(uint32_t v, float *a, float *b, float *c)
{
union
{
uint32_t u32;
struct
{
uint32_t value1 : 10;
uint32_t value2 : 10;
uint32_t value3 : 10;
};
} u = {.u32 = v,};
*a = DeScale(u.value1);
*b = DeScale(u.value2);
*c = DeScale(u.value3);
}
и в основном
coded = Code10(a, b, c);
DeCode10(coded, &d, &e, &f);
printf("Original values: %f,%f,%f. Coded = %x. Decoded %f,%f,%f\n", a, b, c, coded, d, e, f);