威纶屏双精度浮点数(double)转单精度浮点数(float)转双整型(unsigned int)整数及短整型(short)小数
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
双精度浮点数转换单精度浮点数
双精度浮点数转换整型数
最近经常需要读取流量计数据,但流量计总量通常采用64位双精度浮点数(double)储存,但无论是电脑组态软件还是触摸屏组态软件,都只能读取32位数据,查询大量资料,不得其法。
只能自己动手!
经过研究,通过威纶触摸屏宏指令,可以将双精度浮点数转为单精度浮点数或整型数据,转换过程分享给大家,希望对遇到相同问题的难兄难弟有帮助。
(没有转换的数据截图)
(转换后的数据截图)
以下为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 (b31)
//指数部分Exponent(E): 8bit (b30-b23)
//尾数部分Mantissa(M) : 23bit (b22-b0)
//单精度的指数部分(E)采用的偏置码为127(E-127)
//双精度(64位)浮点数的结构:
//符号位Sign(S): 1bit (b63)
//指数部分Exponent(E): 11bit (b62-b52)
//尾数部分Mantissa(M): 52bit (b51-b0)
//双精度的指数部分(E)采用的偏置码为1023(E-1023)
//转换原理:单精度浮点和双精度浮点符号位相同,将双精度的指数转换为单精度的指数,取双精度浮点数尾数部分52位的前23位作为单精度浮点数的尾数部分
//*******************************************
//将流量计总量双精度浮点数按4个16位无符号整型(unsigned short)数据储存在LW10、LW11、LW12、LW13寄存器,计算后的单精度浮点数储存在LW16、LW17(顺序CDAB)。
macro_command main()
bool bit[48],ba[8] //bit-原浮点数位;ba-
short e[2] //e-指数值
GetData(bit[0], "Local HMI", LW_Bit, 1000, 48) //按位提取前48位,注意,每个字节提取的16位二进制数与需要的数相反,即:二进制数为1111000001010101,排序1010101000001111,后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) //将单精度浮点数指数数值写入LW15寄存器
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]
//单精度浮点[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]
//单精度浮点[31]=bit[15]
(原程序截图)
以下为doule转unsigned int 整数+short小数原程序及标注
//威纶屏64位双精度浮点转换为32位整数、4位小数
//实用于威纶屏读取流量计双精度浮点(doule)数据,威纶屏无法直接读取,可将双精度浮点数转为整数部分和小数部分分开储存,32位整数可达4294967295以内真实值,保留4位小数。
//双精度浮点数的结构:
//符号位Sign(S): 1bit (b63)
//指数部分Exponent(E): 11bit (b62-b52)
//尾数部分Mantissa(M): 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] //e-指数及指数偏置;xiao-小数计算值;dizhi-整数位写入地址
unsigned int zheng=0 //zheng-超出范围时整数写0
float guao //guao-小数位计算过渡值
GetData(bit[0], "Local HMI", LW_Bit, 1000, 64) //按位提取数据,注意,每个字节提取的16位二进制数与需要的数相反,即:提取的二进制数为1111000001010101,实际值是1010101000001111
SetData(bit[4], "Local HMI", LW_Bit, 1400, 11) //将双精度浮点数指数部分按位储存
到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]
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]
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位数
dizhi[1]=100+dizhi[0] //整数位开始地址
if e[2]>0 and e[2]<32 then //只计算整数在1-4294967295之间的值
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]
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]
//计算小数部分数值
guao=a[e[2]]*0.5 //1位小数
guao=guao+a[e[3]]*0.25 //2位小数
guao=guao+a[e[4]]*0.125 //3位小数
guao=guao+a[e[5]]*0.0625 //4位小数
guao=guao+a[e[6]]*0.03125 //5位小数
guao=guao+a[e[7]]*0.015625 //6位小数
guao=guao+a[e[8]]*0.0078125 //7位小数
guao=guao+a[e[9]]*0.00390625 //8位小数
guao=guao+a[e[10]]*0.0001953125 //9位小数
guao=guao+a[e[11]]*0.00009765625 //10位小数
guao=guao+a[e[12]]*0.000048828125 //11位小数
guao=guao+a[e[13]]*0.0000244140625 //12位小数
guao=guao+a[e[14]]*0.00001220703125 //13位小数
guao=guao+a[e[15]]*0.000006103515625 //14位小数
guao=guao+a[e[16]]*0.0000030517578125 //15位小数
guao=guao+a[e[17]]*0.00000152587890625 //16位小数
guao=guao*10000 //小数取4位整
xiao=guao //小数取4位
SetData(c[0], "Local HMI", LW_Bit, 2000, 32) //整数值写入到LW20、LW21 SetData(xiao, "Local HMI", LW, 22, 1) //小数值写入到LW22
else
SetData(zheng, "Local HMI", LW, 20, 1) //如果整数超出范围值为0 end if
end macro_command
(原程序截图a)
(原程序截图b)
下面用实际数计算看实际效果:
流量计总量4个16位数分别是:16673、43337、36770、0;用十六进制表示为:4121、A9B7、8FA2、0。
单精度浮点数屏值为:578779.75
整型计算数屏值为:578779.7776
浮点数转换器值为:578779.78053283691
手工计算值为:578779.77766265869140625
那一个值更准确我也不知道,计算过程看以下截图参考。
(流量计数值截图)
(威纶屏计算截图)
从上图可以看出:
单精度浮点数为:578779.75
整型计算数为:578779.7776
二进制数有效位为:0 10000010010 0001101010011011011 1100011111010001
浮点数转换器
(浮点数转换器截图) 浮点数转换器值为:578779.78053283691
手工计算
(浮点数转换器截图)手工计算值:578779.77766265869140625。