admin管理员组

文章数量:1586253

2024年2月9日发(作者:)

双精度浮点数转换单精度浮点数

双精度浮点数转换整型数

最近经常需要读取流量计数据,但流量计总量通常采用64位双精度浮点数(double)储存,但无论是电脑组态软件还是触摸屏组态软件,都只能读取32位数据,查询大量资料,不得其法。只能自己动手!

经过研究,通过威纶触摸屏宏指令,可以将双精度浮点数转为单精度浮点数或整型数据,转换过程分享给大家,希望对遇到相同问题的难兄难弟有帮助。

(没有转换的数据截图)

(转换后的数据截图)

1

以下为doule转float原程序:

双精度浮点数转换单精度浮点数比较容易,将以下代码复制到宏文件即可。

macro_command main()

bool bit[48],ba[8]

short e[2]

GetData(bit[0], "Local HMI", LW_Bit, 1000, 48)

SetData(bit[4], "Local HMI", LW_Bit, 1400, 11)

GetData(e[0], "Local HMI", LW, 14, 1)

e[1]=e[0]-1023+127

SetData(e[1], "Local HMI", LW, 15, 1)

GetData(ba[0], "Local HMI", LW_Bit, 1500, 8)

SetData(bit[45], "Local HMI", LW_Bit, 1600, 3)

SetData(bit[16], "Local HMI", LW_Bit, 1603, 16)

SetData(bit[0], "Local HMI", LW_Bit, 1703, 4)

SetData(ba[0], "Local HMI", LW_Bit, 1707, 8)

SetData(bit[15], "Local HMI", LW_Bit, 1715, 1)

end macro_command

如果看不懂,以下是加标注的完整原程序,供大家参考。

以下为doule转float原程序及标注:

//威纶屏双精度浮点数(doule)转换为单精度浮点数(float)

//最近经常碰到用威纶屏读取流量计数据,但流量计总量数据经常采用双精度浮点数储存,无法直接读取,只能将双精度浮点数转换为单精度浮点数,虽然转换后的数值有点差异,但基本能满足用户使用。

//单精度浮点和双精度浮点主要差异在指数部分和尾数位数

//单精度(32位)浮点数的结构:

//符号位Sign(S): 1bit

8bit

(b31)

(b30-b23) //指数部分Exponent(E):

//尾数部分Mantissa(M) : 23bit (b22-b0)

//单精度的指数部分(E)采用的偏置码为127(E-127)

//双精度(64位)浮点数的结构:

//符号位Sign(S): 1bit (b63)

//指数部分Exponent(E):

//尾数部分Mantissa(M):

11bit (b62-b52)

52bit (b51-b0)

//双精度的指数部分(E)采用的偏置码为1023(E-1023)

2

//转换原理:单精度浮点和双精度浮点符号位相同,将双精度的指数转换为单精度的指数,取双精度浮点数尾数部分52位的前23位作为单精度浮点数的尾数部分

//*******************************************

//将流量计总量双精度浮点数按4个16位无符号整型(unsigned short)数据储存在LW10、LW11、LW12、LW13寄存器,计算后的单精度浮点数储存在LW16、LW17(顺序CDAB)。

macro_command main()

bool bit[48],ba[8]

short e[2]

//bit-原浮点数位;ba-

//e-指数值

//按位提取前48位,注意,每个字节GetData(bit[0], "Local HMI", LW_Bit, 1000, 48)

提取的16位二进制数与需要的数相反,即:二进制数为1111,排序1111,后16位舍弃

SetData(bit[4], "Local HMI", LW_Bit, 1400, 11)

到LW14寄存器

GetData(e[0], "Local HMI", LW, 14, 1)

//计算单精度浮点数指数

e[1]=e[0]-1023+127

SetData(e[1], "Local HMI", LW, 15, 1)

存器

GetData(ba[0], "Local HMI", LW_Bit, 1500, 8) //按位读取单精度浮点数指数部分

//按位将单精度浮点数写入到LW16、LW17寄存器。LW16、LW17即为屏可以读取的float值(屏读取float值时,读取顺序是CDAB,所以AB写入LW17,CD写入LW16)

SetData(bit[45], "Local HMI", LW_Bit, 1600, 3)

SetData(bit[16], "Local HMI", LW_Bit, 1603, 16)

SetData(bit[0], "Local HMI", LW_Bit, 1703, 4)

SetData(ba[0], "Local HMI", LW_Bit, 1707, 8)

SetData(bit[15], "Local HMI", LW_Bit, 1715, 1)

end macro_command

//位计算方法如下

//单精度浮点[0]=bit[45]

3

//将双精度浮点数指数部分按位储存 //读取双精度浮点数指数数值

//将单精度浮点数指数数值写入LW15寄

//单精度浮点[1]=bit[46]

//单精度浮点[2]=bit[47]

//单精度浮点[3]=bit[16]

//单精度浮点[4]=bit[17]

//单精度浮点[5]=bit[18]

//单精度浮点[6]=bit[19]

//单精度浮点[7]=bit[20]

//单精度浮点[8]=bit[21]

//单精度浮点[9]=bit[22]

//单精度浮点[10]=bit[23]

//单精度浮点[11]=bit[24]

//单精度浮点[12]=bit[25]

//单精度浮点[13]=bit[26]

//单精度浮点[14]=bit[27]

//单精度浮点[15]=bit[28]

//单精度浮点[16]=bit[29]

//单精度浮点[17]=bit[30]

//单精度浮点[18]=bit[31]

//单精度浮点[19]=bit[0]

//单精度浮点[20]=bit[1]

//单精度浮点[21]=bit[2]

//单精度浮点[22]=bit[3]

//单精度浮点[23]=ba[0]

//单精度浮点[24]=ba[1]

//单精度浮点[25]=ba[2]

//单精度浮点[26]=ba[3]

//单精度浮点[27]=ba[4]

//单精度浮点[28]=ba[5]

//单精度浮点[29]=ba[6]

4

//单精度浮点[30]=ba[7]

//单精度浮点[31]=bit[15]

(原程序截图)

5

以下为doule转unsigned int 整数+

short小数原程序及标注

//威纶屏64位双精度浮点转换为32位整数、4位小数

//实用于威纶屏读取流量计双精度浮点(doule)数据,威纶屏无法直接读取,可将双精度浮点数转为整数部分和小数部分分开储存,32位整数可达4294967295以内真实值,保留4位小数。

//双精度浮点数的结构:

//符号位Sign(S): 1bit (b63)

//指数部分Exponent(E):

//尾数部分Mantissa(M):

11bit (b62-b52)

52bit (b51-b0)

//双精度的指数部分(E)采用的偏置码为1023(E-1023)

//转换原理,流量计数据可忽略符号位,直接按指数位移位尾数,将尾数部分整数直接读出,小数部分计算储存为短整型

//**************************

//将流量计总量双精度浮点数按4个16位无符号整型(unsigned short)数据储存在LW10、LW11、LW12、LW13寄存器,计算后的32位整数储存在LW20、LW21(顺序CDAB),小数储存在LW22。

macro_command main()

bool

bit[64],a[64],b[32],c[32],d[32]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} //bit-原数位;a-排序位;b-未整理整形位;c-整理后整形位;d-整数位未用补0

short e[18],xiao,dizhi[2]

地址

unsigned int zheng=0

float guao

//zheng-超出范围时整数写0

//guao-小数位计算过渡值

//按位提取数据,注意,每个字节提//e-指数及指数偏置;xiao-小数计算值;dizhi-整数位写入GetData(bit[0], "Local HMI", LW_Bit, 1000, 64)

取的16位二进制数与需要的数相反,即:提取的二进制数为1111,实际值是1111

SetData(bit[4], "Local HMI", LW_Bit, 1400, 11)

6

//将双精度浮点数指数部分按位储存

到LW14寄存器

GetData(e[0], "Local HMI", LW, 14, 1)

//计算单精度浮点数指数实际值及小数位偏置

//读取双精度浮点数指数数值

e[1]=e[0]-1023

e[2]=e[1]+1

e[3]=e[2]+1

e[4]=e[3]+1

e[5]=e[4]+1

e[6]=e[5]+1

e[7]=e[6]+1

e[8]=e[7]+1

e[9]=e[8]+1

e[10]=e[9]+1

e[11]=e[10]+1

e[12]=e[11]+1

e[13]=e[12]+1

e[14]=e[13]+1

e[15]=e[14]+1

e[16]=e[15]+1

e[17]=e[16]+1

//计算尾数部分数值

a[0]=1

a[1]=bit[3]

a[2]=bit[2]

a[3]=bit[1]

a[4]=bit[0]

a[5]=bit[31]

a[6]=bit[30]

a[7]=bit[29]

7

a[8]=bit[28]

a[9]=bit[27]

a[10]=bit[26]

a[11]=bit[25]

a[12]=bit[24]

a[13]=bit[23]

a[14]=bit[22]

a[15]=bit[21]

a[16]=bit[20]

a[17]=bit[19]

a[18]=bit[18]

a[19]=bit[17]

a[20]=bit[16]

a[21]=bit[47]

a[22]=bit[46]

a[23]=bit[45]

a[24]=bit[44]

a[25]=bit[43]

a[26]=bit[42]

a[27]=bit[41]

a[28]=bit[40]

a[29]=bit[39]

a[30]=bit[38]

a[31]=bit[37]

a[32]=bit[36]

a[33]=bit[35]

a[34]=bit[34]

a[35]=bit[33]

a[36]=bit[32]

8

a[37]=bit[63]

a[38]=bit[62]

a[39]=bit[61]

a[40]=bit[60]

a[41]=bit[59]

a[42]=bit[58]

a[43]=bit[57]

a[44]=bit[56]

a[45]=bit[55]

a[46]=bit[54]

a[47]=bit[53]

a[48]=bit[52]

a[49]=bit[51]

a[50]=bit[50]

a[51]=bit[49]

a[52]=bit[48]

//计算整数位写入过渡地址(LB100-LB131)

dizhi[0]=32-e[2]

//补0位数

//整数位开始地址

//只计算整数在1-4294967295之间dizhi[1]=100+dizhi[0]

if e[2]>0 and e[2]<32 then

的值

SetData(d[0], "Local HMI", LB, 100, dizhi[0]) //空位补0

SetData(a[0], "Local HMI", LB, dizhi[1], e[2])

GetData(b[0], "Local HMI", LB, 100, 32)

//计算整型位实际值位排序

c[0]=b[31]

c[1]=b[30]

c[2]=b[29]

c[3]=b[28]

9

//写入整数实际值

//取出整数位

c[4]=b[27]

c[5]=b[26]

c[6]=b[25]

c[7]=b[24]

c[8]=b[23]

c[9]=b[22]

c[10]=b[21]

c[11]=b[20]

c[12]=b[19]

c[13]=b[18]

c[14]=b[17]

c[15]=b[16]

c[16]=b[15]

c[17]=b[14]

c[18]=b[13]

c[19]=b[12]

c[20]=b[11]

c[21]=b[10]

c[22]=b[9]

c[23]=b[8]

c[24]=b[7]

c[25]=b[6]

c[26]=b[5]

c[27]=b[4]

c[28]=b[3]

c[29]=b[2]

c[30]=b[1]

c[31]=b[0]

//计算小数部分数值

10

guao=a[e[2]]*0.5

//1位小数

//2位小数

//3位小数

guao=guao+a[e[3]]*0.25

guao=guao+a[e[4]]*0.125

guao=guao+a[e[5]]*0.0625

guao=guao+a[e[6]]*0.03125

//4位小数

//5位小数

//6位小数 guao=guao+a[e[7]]*0.015625

guao=guao+a[e[8]]*0.0078125

guao=guao+a[e[9]]*0.00390625

guao=guao+a[e[10]]*0.

guao=guao+a[e[11]]*0.

guao=guao+a[e[12]]*0.

guao=guao+a[e[13]]*0.5

guao=guao+a[e[14]]*0.25

guao=guao+a[e[15]]*0.625

guao=guao+a[e[16]]*0.8125

guao=guao+a[e[17]]*0.90625

guao=guao*10000

xiao=guao

SetData(c[0], "Local HMI", LW_Bit, 2000, 32)

SetData(xiao, "Local HMI", LW, 22, 1)

else

SetData(zheng, "Local HMI", LW, 20, 1)

end if

end macro_command

11

//7位小数

//8位小数

//9位小数

//10位小数

//11位小数

//12位小数

//13位小数

//14位小数

//15位小数

//16位小数

//小数取4位整

//小数取4位

//整数值写入到LW20、LW21

//小数值写入到LW22

//如果整数超出范围值为0

(原程序截图a)

12

(原程序截图b)

13

下面用实际数计算看实际效果:

流量计总量4个16位数分别是:16673、43337、36770、0;用十六进制表示为:4121、A9B7、8FA2、0。

单精度浮点数屏值为:578779.75

整型计算数屏值为:578779.7776

浮点数转换器值为:578779.78053283691

手工计算值为:578779.77766265869140625

那一个值更准确我也不知道,计算过程看以下截图参考。

(流量计数值截图)

(威纶屏计算截图)

从上图可以看出:

单精度浮点数为:578779.75

整型计算数为:578779.7776

二进制数有效位为:0 1 1011011 1101

14

浮点数转换器

(浮点数转换器截图)

浮点数转换器值为:578779.78053283691

手工计算

(浮点数转换器截图)

手工计算值:578779.77766265869140625

15

本文标签: 浮点数单精度精度部分计算