今天调试一台设备时,在交互的Modbus协议中,设定数值位用的是浮点数。

带过那么多学生,我竟然脑袋一空??!

Modbus用浮点型?

浮点型与U32互转?

16位 是浮点运算吗 16位浮点和32位浮点转化_c++

于是硬着头皮,重新把这块的内容,复盘了一遍~~现在整理笔记,分享给大家。

明天可能会依据这个出个QT的demo,需要的可以一蹲!

一、浮点数与16进制的转化概念

对于一个32位的浮点数中,有以下三个部分组成:符号位、阶码和尾数。具体格式如下:

16位 是浮点运算吗 16位浮点和32位浮点转化_qt_02

对各部分解释如下:

S:浮点数的符号位,1 位。0表示正数,1表示负数。

M:尾数,23位。用小数表示,小数点在尾数域前面。

E:阶码,采用移码方式来表示。

作用:移码方法对两个指数大小的比较和对阶操作都比较方便,因为阶码域值大者其指数值也大。

采用移码方法时,需要将浮点数的指数真值e变成阶码E,变换方法是将指数 e 加上一个固定的偏移值127(01111111),即 E=e+127

浮点数的真值x计算格式为:x = (-1)^s × (1.M) × 2^e

32位浮点数e=E-127;64位浮点数e = E-1023



简单举几个例子:

例题1. 若浮点数x的二进制存储格式为(41360000)16进制,求其32位浮点数的值。
将16进制数转换为2进制 0100 0001 0011 0110 0000 0000 0000 0000
则e = 10000010 - 01111111 = 3(十进制)
M = 01101100000000000000000
则x = (-1)^0 × 1.011011× 2^3 = 1011.011(2进制)
= 11.375(十进制)

例题2.    将十进制数20.59375转换成32位浮点数。
       首先分别将整数和分数部分转换成二进制数:
              20.59375=10100.10011
  然后移动小数点,使其在第1,2位之间
    10100.10011=1.010010011 × 2^4   e=4
  于是得到:
             S=0,E=4+127=131,M=010010011
  最后得到32位浮点数的二进制存储格式为:
           0100 0001 1010 0100 1100 0000 0000 0000
        =41A4C000(16进制)

二、浮点数与16进制的转化概念

以QT编译器为例,C/C++针对float浮点型与16进制转换的实现如下:

#include <stdio.h>
float Hex_To_Decimal(unsigned char *Byte,int num)//十六进制到浮点数
{
//      char cByte[4];//方法一
//     for (int i=0;i<num;i++)
//     {
//     cByte[i] = Byte[i];
//     }
//     float pfValue=*(float*)&cByte;
//return  pfValue;
        return *((float*)Byte);//方法二
}

long FloatTohex(float f_tohex)//浮点数到十六进制转换1
{
    return *( long *)&f_tohex;
}

void FloatToByte(float floatNum,unsigned char* byteArry)/*浮点数到十六进制转换2*/
{
    char* pchar=(char*)&floatNum;
    for(int i=0;i<sizeof(float);i++)
    {
        *byteArry=*pchar;
        pchar++;
        byteArry++;
    }
}

int main(int argc, char *argv[])
{
    unsigned char floatToHex[4];
    uint32_t float_32;
    uint8_t u8_f32[4];

    unsigned    char hexbyte[4]={0xcd,0xCC,0xCC,0x3D};//传输数据为3d cc cc cd
    float Hdecimal=0.0;
    float flh=2.0;

    Hdecimal=Hex_To_Decimal(hexbyte,sizeof(hexbyte));//十六进制转换为浮点数
//    printf("\n 浮点数为:\n %f\n",Hdecimal);
    qDebug()<<QString(" 浮点数为:%1").arg(Hdecimal);

    long hX=FloatTohex(Hdecimal);//浮点数转换为十六进制一
//    printf("\n正序十六进制值:\n %f=%X \n",Hdecimal,hX);//正序显示
    qDebug()<<QString(" 正序十六进制值:%1 => %2").arg(hX).arg(Hdecimal);

    FloatToByte(Hdecimal,floatToHex);//浮点数转为十六进制二
//    printf("\n倒序十六进制:\n%f=%x %x %x %x\n",Hdecimal,floatToHex[0],floatToHex[1],floatToHex[2],floatToHex[3] );//倒序显示
    qDebug()<<QString(" 倒序十六进制:%1=%2 %3 %4 %5").arg(Hdecimal).arg(QString::number(floatToHex[0], 16).toUpper()).arg(QString::number(floatToHex[1], 16).toUpper()).arg(QString::number(floatToHex[2], 16).toUpper()).arg(QString::number(floatToHex[3], 16).toUpper());
    
    FloatToByte(flh,floatToHex);//浮点数转为十六进制二
    qDebug()<<QString(" 倒序十六进制:%1=%2 %3 %4 %5").arg(flh).arg(QString::number(floatToHex[0], 16).toUpper()).arg(QString::number(floatToHex[1], 16).toUpper()).arg(QString::number(floatToHex[2], 16).toUpper()).arg(QString::number(floatToHex[3], 16).toUpper());
    qDebug()<<QString(" 正序十六进制:%1=%2 %3 %4 %5").arg(flh).arg(QString::number(floatToHex[3], 16).toUpper()).arg(QString::number(floatToHex[2], 16).toUpper()).arg(QString::number(floatToHex[1], 16).toUpper()).arg(QString::number(floatToHex[0], 16).toUpper());
}

PS:以上代码,只简单例举了浮点型与16进制的转换,那么浮点型和U32的转换,你能举一反三实现出来吗?

明天会发一个基于QT的demo进行揭晓哟!欢迎一蹲!