将4个原始字节转换为32位浮点

时间:2014-10-11 01:50:08

标签: c++ c floating-point floating-point-conversion

我试图从eeprom重建一个32位浮点值。

eeprom存储器(0-4)中的4个字节是:B4 A2 91 4D

并且PC(VS Studio)正确地将其重建为3.054199 * 10 ^ 8(我知道浮点值应该在那里)

现在我将这个eeprom从8位Arduino中读取,所以不确定它是否是编译器/平台的东西,但是当我尝试将4个字节读入32位双字节时,然后将它转换为浮点数,我得到的值甚至不接近。

假设转换不能使用标准的ansi-c编译器自动完成,那么如何将4个字节手动解析成浮点数?

3 个答案:

答案 0 :(得分:10)

最安全的方式,也是由于编译器优化也和其他任何方法一样快,是使用memcpy

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

演示:http://ideone.com/riDfFw

答案 1 :(得分:1)

正如Shafik Yaghmour在他的回答中提到的那样 - 它可能是一个endianness问题,因为这是您在这种低级别操作中遇到的唯一逻辑问题。虽然Shafiks answer在他所关联的问题中,基本上涵盖了处理此类问题的过程,但我只是给您留下一些信息:

在Anduino论坛上作为stated,Anduino使用 Little Endian 。如果您不确定系统的最终结果是什么,而您希望将代码设置为半多平台,则可以使用简单的代码片段在运行时检查字节顺序:

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

请注意 - 就像所有事情一样 - 这会消耗你的一些处理器时间并使你的程序运行得更慢,虽然这几乎总是一件坏事,你仍然可以使用它来查看调试中的结果你的应用版本。

这是如何工作的,它测试存储在int指向的地址的&number的第一个字节。如果第一个字节不是1,则表示字节为 Big Endian

此外 - 仅在sizeof(int) > sizeof(char)时才有效。

您也可以将其嵌入代码中:

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;
}

答案 2 :(得分:0)

你需要在指针级别进行强制转换。

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

应该工作。

如果数据是在存储相反字节序的值的其他平台上生成的,则您需要手动交换字节。 E.g:

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