在Delphi下 IEEE32位浮点数到十进制Integer的相关转换和处理

Delphi 专栏收录该内容
3 篇文章 0 订阅

许多工控设备仪器传输的数据都是IEEE 32位浮点数格式的,因此在上下位机通信后,需要转换成整数或者其他字符串格式的,以便后续处理。

遵从IEEE制定的浮点数表示法规定的编译器和开发环境,因为用二进制来表示实数(浮点数)不是一件很容易的事情,所以浮点运算也是相当费计算资源的。浮点运算使用了三种数据类型:整数(integer);实数(在Delphi里叫Real,在PC的C/C++开发环境里叫float),它包含Single Real和double Real分别对应C++的float和double数据类型;最后是BCD二进制数。

下面是其位数(bits)和能表示的大致范围和
Type Length Range
-----------------------------------------------
Word Integer 16 bit -32768 to 32768
Short Integer 32 bit -2.14e9 to 2.14e9
Long Integer 64 bit -9.22e18 to 9.22e18
Single Real 32 bit 1.18e-38 to 3.40e38   (对应Delphi里面的Single和Real类型,对应C里面的float)
Double Real 64 bit 2.23e-308 to 1.79e308
extended Real 80 bit 3.37e-4932 to 1.18e4932
Packed BCD 80 bit -1e18 to 1e18

那么这个浮点数,该如何换算成为需要定点位数的十进制小数(整数)呢?看一下浮点数的具体规格定义:

````````符号位 阶码 尾数 长度
float        1       8      23   32bits(4 Bytes)
double   1     11      52   64bits(8 Bytes)
临时数    1    15      64   80bits(10 Bytes)

按照科学计数法,实数浮点数的写法如下。
科学记数法的形式是由两个数的乘积组成的。表示为a×10^b,(计算器或电脑表达10的的幂是一般是用E或e,也就是aEb)
其中一个因数为a(绝对值范围:1≤|a|<10),另一个因数为10^n(n是比A的整数部分少1的正整数)。

下面这个例子,就是float类型32bits数据转换的一个代表:

------------------------------------------

例如某计算机通过MODBUS协议读到的流量计内部的数据:


流量计计算机通过485端口以MODBUS协议把内部IEEE32位浮点数传送到DCS的数据   经过研究试验,其数据格式如下   

数据请求依次为:十六进制
  从站地址:01;读命令:03;数据起始高位地址:0F;数据起始低位地址:A0;(0FA0=4000即地址44001);数据长度高位:00;数据长度低位:28;(0028=40即40个地址);CRC效验码:46,E2   

数据应答格式:
从站地址:01;读命令反馈:03;数据长度:50;第一个地址:69;C0;48;A9;第二个地址:C5;00;48;A2;以下类推,直到最后两位CRC:E8;86   

第一个地址:69;C0;48;A9是如何换算为346958的呢?   

因为流量计发送的是IEEE标准的32位浮点数,

首先要把69;C0;48;A9进行高低16位交换变成:48;A9;69;C0       (注:这是流量计自己的格式顺序定义!在x86的PC架构里是四个字节倒序的!!)
再变为32位二进制数:01001000  10101001  01101001  11000000   其中最高位为0,代表是正数

接下来的八位:10010001变成十进制是145,根据IEEE规范应减去127得18,这是小数点右移的位数; 
剩下的23位是纯二进制小数即:0.0101001  01101001  11000000   加1后得1.0101001  01101001  11000000 
小数点右移18位后得10101001  01101001  110.00000   变为十进制得346958 

其它地址的32位浮点数计算方法同上

------------------------------------------------------------------------------------

浮点数:长度为4字节。其中尾数高位始终为1,位的分布如下:
&#61548; 1为符号位
&#61548; 8为指数位
&#61548; 23位尾数
符号位是最高位,尾数位最低23位,按字节保存如下:
   地址:        +0            +1            +2           +3
   内容:  MMMM MMMM         MMMM MMMM    EMMM MMMM    SEEE EEEE
其中:S:符号位,0=正,1=负
       E:指数(在两个字节中),偏移为127。
       M:23位尾数,最高位为“1”。
 例如:浮点数-12.5的十六进制为0XC1480000,它按下面方式存储:
   地址:     +0           +1           +2           +3
   内容:    0X00         0X00         0X48        0XC1
请问:如何转换,互换

----------------------------------------------------------------------

4字节,从低位到高位排列,记为031位,其中0位为符号位,为0时表示为正数,为1时表示为负数。
当为正数时,18位为A,则 =A-10000000,转换幂为十进制数,记为M931位,将隐含的小数点后移M位,然后转换此数为十进制即可;
当为负数时,取18位为B,则 =B取反后-10000000,转换幂为十进制数N931位取反后加1,再将隐含的小数点后移N位,然后转换此数为十进制即可。
请大侠赐教。用C++或者MFC实现均可。不胜感激!

 

int  s; //符号
char e; //
指数
int  f=1; //
尾数
int  d; //
转换你那鸟数的数
int  d2;//
这也是用来转换你那鸟数的
int  m,n;//
整数部分,和小数据部分
kkk  x; //
你说的那个鸟LIA格式的浮点数

d=*(int*)&x;
s=d&0x00000001;
e=(d>>1)&0x7f;
d2=(d>>8)&0x00ffffff;
for(int i=0;i<24;i++)
{
   f<<1;
   f|=(d2>>i)&0x00000001;
}
if(s)
{
    e=~e;
    e&=0xff;
    e-=0x80;
    m=f>>(24-e);
    n=(f<<(7+e))>>31;
}
else
{
    e-=0x80;
    f=~f;
    f&=0x00ffffff;
    f++;
    m=f>>(24-e);
    n=(f<<(7+e))>>31;


printf("
你那个鸟数就是:%d.%d\n",m,n);



『Delphi和C++数据类型对照表』
Delphi            字长/值域                                C++

ShortInt          8位有符号整型                          signed char
SmallInt          16位有符号整型                         short
LongInt           32位有符号整型                         int
Byte              8位无符号整型                          unsigned char
Word              16位无符号整型                         unsigned short
Integer           32位有符号整型                         int
Cardinal          32位无符号整型                         unsigned int
DWord             32位无符号整型                         unsigned int
Boolean           真/假                                  bool
ByteBool          真/假 或 8位无符号整型                 unsigned char
WordBool          真/假 或 16位无符号整型                unsigned short
LongBool          真/假 或 32位无符号整型                BOOL (WinAPI)
AnsiChar          8位无符号字符                          char
WideChar          宽字编码字符                           wchar_t
Char              8位无符号字符                          char
AnsiString        Delphi的字符串类                       AnsiString 类
String[n]         老式的Delphi字符串, n = 1..255字节     SmallString<n> 模板类
ShortString       老式的Delphi字符串, 255字节            SmallString<255>
String            Delphi的AnsiString类                   AnsiString
Single            32位浮点数                             float
Double            64位浮点数                             double
Extended          80位浮点数                             long double
Real              32位浮点数                             double
Pointer           32无类型指针                           void *



  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值