How to : Convert byte array to float array

I'm new to programming, can you help me, please?
I have a 16-byte array that I need to convert into an array of 4 floats in big-endian format.

byte new_data[]={0xF,0x7F,0x3A,0x46,0x3D,0x96,0x87,0x35,0x3B,0xD7,0x11,0x8B,0x3C,0xC5,0x3A,0x7B}; 
float Q[4];

Thanks in advance.

If the bytes are supposed to represent float values, then they can be combined in two different ways, depending on the whether the byte order is big or little endian.

Which way depends on what computers and MCUs you are using.

I receive data from a sensor to esp32 and in the datasheet of the sensor the data must be converted to a float using big-endian format as I mentioned in the topic

This should give you some ideas, although the C++ clerics will not approve of using a union.

// float to byte, Arduino Uno byte order
union equiv {
  float x;
  unsigned long l;
  byte buf[4];
} equiv ;

void setup() {
 Serial.begin(115200);
 equiv.l = 0x42D20000;
 Serial.print("float value ");
 Serial.println(equiv.x);
 for (int i=0; i<4; i++) Serial.println(equiv.buf[i],HEX);
}

void loop() {
}

This seems to give sensible output (0.00, 0.07, 0.01, 0.02):

for (size_t i = 0; i < 4; i++) {
  uint32_t tmp = 0;
  for (size_t j = 0; j < 4; j++) {
    tmp |= static_cast<uint32_t>(new_data[4 * i + j]) << 8 * (3 - j);
  }
  Q[i] = *reinterpret_cast<float*>(&tmp);
}

If the byte order needs to be reversed, (3 - j) should be replaced with j.

Apologies in advance for the reinterpret_cast.

[edit]

This is probably better:

memcpy(&Q[i], &tmp, sizeof(float));

[edit2]

The following is probably safer as it does not rely on float being 4 bytes.

size_t const fSize = sizeof(float);
for (size_t i = 0; i < sizeof(new_data) / fSize; i++) {
  uint8_t tmp[fSize];
  for (size_t j = 0; j < fSize; j++) {
    tmp[j] = new_data[fSize * i + fSize - j - 1];
  }
  memcpy(&Q[i], &tmp, fSize);
}

1. 0x0F7F3A46 is the binary32 formatted bit stream for 1st float number.
Converting 0x0F7F3A46 into float number using memcpy() function.

  float y1;
  long m = 0x0F7F3A46;
  memcpy(&y1, &m, sizeof y1); //destination, source
  Serial.println(y1, 2);  //y1 = 0.00

2. 0x3D968735 is the binary32 formatted bit stream for 2nd float number.
3. 0x3BD7118B is the binary32 formatted bit stream for 3rd float number.
4. 0x3CC53A7B is the binary32 formatted bit stream for 4th float number.

Now, use for() loop to transform the data items of the new_data[] array into float numbers and save in array float Q[].

The quick and dirty way..

byte new_data[] = {0xF,0x7F,0x3A,0x46,0x3D,0x96,0x87,0x35,0x3B,0xD7,0x11,0x8B,0x3C,0xC5,0x3A,0x7B}; 
float *Q = (float*)new_data;
for (int i = 0; i < 4; i++) Serial.println(Q[i]);

This is the output of your program which is wrong:

11935.76
0.00
-0.00
ovf

The correct output is:

0.00
0.07
0.01, and
0.02

Sorry, I missed the endianness, easy to fix by reversing the bytes..

byte new_data[] = {0xF,0x7F,0x3A,0x46,0x3D,0x96,0x87,0x35,0x3B,0xD7,0x11,0x8B,0x3C,0xC5,0x3A,0x7B};
byte nd_size = sizeof(new_data);
byte reversed[nd_size];
for (int i = 0; i < nd_size; i++) reversed[i] = new_data[nd_size - 1 - i];
float *Q = (float*)reversed;
byte n_floats = nd_size / 4;
for (int i = 0; i < n_floats; i++) Serial.println(Q[n_floats - 1 - i]);

This time is good:

0.00
0.07
0.01
0.02

Thank you, it worked.

Thank you, it worked in both cases, but I will use the solution after the modification :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.