用C解释浮点数据

时间:2013-10-29 07:04:27

标签: c++ c casting floating-point int

我正在调试缓冲区中出现的数据错误值的问题。我将缓冲区(u8)类型从内核驱动程序发送到HAL。在HAL中有一个Uint16缓冲区,它接收来自此缓冲区的值。

//Code to copy BUFFLEN contents from u8 data[BUFFLEN] into uint16_tData ;

uint16_t uint16_tData[BUFFLEN / 2];
float floatdata[BUFFLEN / 2];

我使用此类型转换从uint16_tData缓冲区获取浮点值:

floatdata[index] = (*((float *)((void *)&uint16_tData[index1];

现在我的问题:如何解释驻留在floatdata数组中的数据? 假设我有数据floatdata[0] = 53640;

如何在floatdata[0]

中解释此半字节中的浮点数据

注意来自u8的4个字节 - >数组的2个元素uint16_tData - >数组floatdata的一个元素。

我想知道一个例子:

从驱动程序传输的值是:

u8 val1 = 206
u8 val2 = 208
u8 val3 = 120
u8 val4 = 68

在HAL中,转换将如何发生以及我将获得什么价值?

uint16_tData[0] = ?
uint16_tData[1] = ?

如何将数据解释为floatdata中的浮点数?

floatdata[0] = ?

4 个答案:

答案 0 :(得分:1)

为什么这样呢?

我想你想要这个:

float *floatdata;

floatdata = (float *)uint16_tData;

// Now use floatdata[index] ...

一次铸造一件物品是愚蠢的。从uint16_t到float的转换甚至更愚蠢,最好将它保持为uint8_t(字节),这似乎是它的内容,或者至少使用uint32_t作为中间体。

有没有什么可以阻止你这样做?您能想到如何重新设计代码以避免完全处理这些问题吗?

答案 1 :(得分:1)

根据我对你的问题的理解,这就是你想要的

float f ;
uint8_t u8arr[4]={206,208,120,68};
uint16_t arr[2];
memcpy(&arr[0],u8arr,2);
memcpy(&arr[1],u8arr+2,2);
memcpy(&f,arr,4);

答案 2 :(得分:1)

uint16由“u8”组成,单精度float为32位(4 u8或2 uint16),但它们如何“转换”取决于处理这些数据的代码,特别是“发送”的含义(来自内核驱动程序)以及“接收”的代码如何期望数据。我承认我对这个主题一无所知,我现在无法检查和研究它,但我怀疑你有 endianness 的问题:你的数据完全具有“含义”,而不是单个八位字节,但是你把它们以错误的顺序存放在内存中。

基本上,你有一个包含你的octect的缓冲区,比如说

A   B   C   D
u8  u8  u8  u8      4 u8 arr element (arr[0], arr[1] ...)
\____/  \____/  
 uint16   uint16    2 uint16 arr element (arr[0] and arr[1]) 

按此顺序增加内存地址。如果您希望A B被读作“正确的”uint16号码,则必须在内存中“排序”它以便匹配处理器的字节序:例如如果你想在一个小端cpu上使用数字A*8 + B,你必须以相反的顺序在内存中写两个u8:

B A D C

我怀疑HAL仅使用uint16来存储数据,而不是将它们解释为16位数,因此这里的字节顺序不是问题。但是,一旦你想在内存中从4 u8(或2 uint16)获得正确的“浮动”:你必须按正确的顺序放置u8。

如果你想让你的u8被解释为通过演员表浮动,你首先必须在一个小端机器中以相反的顺序放置它们,例如。

  address of arr8[0] and arr16[0]
/
D   C   B   A
u8  u8  u8  u8      4 u8 arr element (arr8[0], arr8[1] ...)
\____/  \____/  
 uint16   uint16    2 uint16 arr element (arr16[0] and arr16[1]) 

然后,如果你“读取”这些八位字节在一个litte endian机器上漂浮,你就有了正确的“浮动”。

因此,你应该正确排序你的u8,因为他们知道它们会被解释为宽度超过一个八位字节的另一种类型。对于具有不同字节序的处理器,可移植代码应使用正确的方法进行正确编译。

另见this wikipedia article

答案 3 :(得分:0)

我不是HAL / DX友好所以它可能是一个愚蠢的注意事项 但你确定你的花车是16位而不是32位吗?

好的,现在你的问题是什么:

  1. 你有uint缓冲区,但是将float存储在里面吗?

    • 在这种情况下只需这样做:

      float16 *p=(float16*)uint16_tData;
      
    • 并使用p而不是uint16_tData
  2. 你有uint缓冲区,其中存储了uint值吗?

    • 这意味着您需要将uint转换为float
    • 如果存在则使用internal = operator
    • 如果没有自己编写转换
    • 你可以忽略对于uints的签名
    • 将exp设为0(2 ^ 0)
    • 将尾数设置为uint值
    • truncate unfitted bits
    • 右移/ inc指数直到uint的MSB适合尾数
    • 将所有位置与位移/和/或放在他们的位置(参见上面的链接)
  3. 您有浮动值,需要将它们存储在uint中作为uint

    • 所以简单地向前做点
    • 提取指数,mantisa,忽略符号或使用2'os补充
    • 通过指数(如果是正面)将mantisa左移,否则通过-exponent
    • 就是这样。
  4. PS。注意某些平台/编译器/数据类型的位移也可以从进位或数字的另一侧插入。在那种情况下,结果使用位掩码。

    PPS。不要忘记应用指数偏见!!!

    希望它有所帮助