Convert 4 raw bytes to 32-bit floating point

I am trying to rebuild a 32bit floating point value from eeprom.

4 bytes in eeprom memory (0-4): B4 A2 91 4D

and PC (VS Studio) will correctly reconstruct it as 3.054199 * 10 ^ 8 (the floating point value I know should be there)

Now I move this eeprom to read from an 8 bit Arduino so not sure if it is a compiler / platform, but when I try to read 4 bytes into a 32 bit dword and then output it to float, the value I get is even not close.

Assuming the conversion cannot be done automatically with the standard ansi-c compiler, how can 4 bytes be manually parsed as a float?

+3


source to share


3 answers


The safest way, and due to compiler optimizations, is just as fast as any other is to use memcpy

:

uint32_t dword = 0x4D91A2B4;
float f;
memcpy(&f, &dw, 4);

      



Demo: http://ideone.com/riDfFw

+9


source


As Shafiq Yagmur mentioned in his answer - it's probably endianness as this is the only logical problem you could run into with such a low level operation. While Shafiks' answer in the question he linked mainly covers the process of handling such an issue, I'll just leave you some information:

As stated on the Anduino forums, Anduino uses Little Endian . If you are not sure what the finiteness of the system will be, you will eventually work, but want your code to be semi-multiplatform, you can check the continent at runtime with a simple code snippet:

bool isBigEndian(){
   int number = 1;
   return (*(char*)&number != 1);
}

      

Consider that - like everything - it consumes some of your CPU time and makes your program run slower, and while this is almost always bad, you can still use this to see the results in a debug version of your application.



The way it works is it checks the first byte int

stored at the address given &number

. If the first byte is not equal 1

, it means Big Endian bytes .

Also - this will only work if sizeof(int) > sizeof(char)

.

You can also paste this into your code:

float getFromEeprom(int address){
   char bytes[sizeof(float)];
   if(isBigEndian()){
      for(int i=0;i<sizeof(float);i++)
         bytes[sizeof(float)-i] = EEPROM.read(address+i);
   }
   else{
      for(int i=0;i<sizeof(float);i++)
         bytes[i] = EEPROM.read(address+i);
   }
   float result;
   memcpy(&result, bytes, sizeof(float));
   return result;
}

      

+1


source


You need to point at the pointer level.

int     myFourBytes = /* something */;
float*  myFloat = (float*) &myFourBytes;
cout << *myFloat;

      

Must work.

If the data is generated on another platform that stores values ​​in the opposite form, you need to manually swap the bytes. For example:.

unsigned char myFourBytes[4] = { 0xB4, 0xA2, 0x91, 0x4D };
std::swap(myFourBytes[0], myFourBytes[3]);
std::swap(myFourBytes[1], myFourBytes[2]);

      

0


source







All Articles