不复制内存,不用union的情况下,将表示float的4个字节转为float

最近遇到个问题,就是通过udp收到4个字节,这4个字节表示的是一个float,由于所用plc板上的结构化文本语言(st)没有memcpy来复制内存,也没有union数据类型,因此只能自己想办法把这4个字节转为float了。

看了这篇文章:float类型的存储方式(https://zhuanlan.zhihu.com/p/82761324)清楚了float是如何转为32位二进制码的,然后就按照这个原则来将4个字节的32位二进制码转为float。

以下为C++代码:

int main()
{
    float f= -123.1958;
    char data[4];
    //用memcpy来模拟通过比方说upd收到的4个字节
    memcpy(data, &f, 4);

    //合并4个单字节
    int num = 0;    
    for(int i = 3; i >= 0; --i)                            // 注意区分高低位
        num = (num<<8)|(data[i]&~(~0<<8));  //1001会扩展为高位全是1,因此只取后8位

    bool negative_flag = num>>31;
    //先取第23到30位,然后减127得到指数
    int e = int((num>>23) & ~(~0<<8)) - 127;   //不加类型转换int时,(num>>23) & ~(~0<<8)的数据类型是?
    int tail = 1<<23 | (num & ~(~0<<23));       //取第0到22位,且23位置为1
    // 去掉尾部补的0
    while((tail & ~1) == tail)
    {
        tail = tail>>1;
    }
    int tmp = ~(~0<<23);
    int cnt;    //tail中最高位的1的位置,即不算高位0的有效的二进制位数
    for(int i = 0; i < 24; ++i)
    {
        if((tmp & tail) == tail)
            tmp = tmp>>1;
        else
        {
            cnt = 24 - i;
            break;
        }
    }
    int integer = tail>>(cnt - e - 1);                  //整数部分,不用再处理了
    int decimal = tail&(~(~0<<(cnt - e - 1)));      //小数部分,还得再处理

    float result = 0;
    for(int decimal_num = cnt - e - 1; decimal_num > 0; --decimal_num)
    {
        // 每次循环是先加上decimal的最低位然后除2,然后decimal右移1位
        result += decimal & 1;
        result /= 2;
        decimal = decimal >> 1;
    }
    result += integer;
    if(negative_flag)
        result = -result;
    printf("%.7f\n", result);
    return 0;
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值