Converting 4 raw bytes into 32-bit floating point

半世苍凉 提交于 2019-12-29 01:43:06

问题


I'm trying to re-construct a 32-bit floating point value from an eeprom.

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

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

Now I'm moving this eeprom to be read from an 8-bit Arduino, so not sure if it's compiler/platform thing, but when I try reading the 4 bytes into a 32-bit dword, and then typecast it to a float, the value I get isn't even close.

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


回答1:


The safest way, and due to compiler optimization also as fast as any other, is to use memcpy:

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

Demo: http://ideone.com/riDfFw




回答2:


As Shafik Yaghmour mentioned in his answer - it's probably an endianness issue, since that's the only logical problem you could encounter with such a low-level operation. While Shafiks answer in the question he linked, basically 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're not sure about what will be the endianness of the system you'll end up working on, but want to make your code semi-multiplatform, you can check the endianness at runtime with a simple code snippet:

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

Be advised that - as all things - this consumes some of your procesor time and makes your program run slower, and while that's nearly always a bad thing, you can still use this to see the results in a debug version of your app.

How this works is that it tests the first byte of the int stored at the address pointed by &number. If the first byte is not 1, it means the bytes are Big Endian.

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

You can also embed this in 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;
}



回答3:


You need to cast at the pointer level.

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

Should work.

If the data is generated on a different platform that stores values in the opposite endianness, you'll need to manually swap the bytes around. E.g.:

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


来源:https://stackoverflow.com/questions/26310249/converting-4-raw-bytes-into-32-bit-floating-point

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!