1、1 双精度浮点数转换单精度浮点数 双精度浮点数转换整型数 最近经常需要读取流量计数据,但流量计总量通常采用64位双精度浮点数(double)储存,但无论是电脑组态软件还是触摸屏组态软件,都只能读取32位数据,查询大量资料,不得其法。只能自己动手! 经过研究,通过威纶触摸屏宏指令,可以将双精度浮点数转为单精度浮点数或整型数据,转换过程分享给大家,希望对遇到相同问题的难兄难弟有帮助。 (没有转换的数据截图) (转换后的数据截图) 2 以下为doule转float原程序: 双精度浮点数转换单精度浮点数比较容易,将以下代码复制到宏文件即可。 macro_command main() bool bit4
2、8,ba8 short e2 GetData(bit0, “Local HMI“, LW_Bit, 1000, 48) SetData(bit4, “Local HMI“, LW_Bit, 1400, 11) GetData(e0, “Local HMI“, LW, 14, 1) e1=e0-1023+127 SetData(e1, “Local HMI“, LW, 15, 1) GetData(ba0, “Local HMI“, LW_Bit, 1500, 8) SetData(bit45, “Local HMI“, LW_Bit, 1600, 3) SetData(bit16, “Loca
3、l HMI“, LW_Bit, 1603, 16) SetData(bit0, “Local HMI“, LW_Bit, 1703, 4) SetData(ba0, “Local HMI“, LW_Bit, 1707, 8) SetData(bit15, “Local HMI“, LW_Bit, 1715, 1) end macro_command 如果看不懂,以下是加标注的完整原程序,供大家参考。 以下为doule转float原程序及标注: /威纶屏双精度浮点数(doule)转换为单精度浮点数(float) /最近经常碰到用威纶屏读取流量计数据,但流量计总量数据经常采用双精度浮点数储存,无法
4、直接读取,只能将双精度浮点数转换为单精度浮点数,虽然转换后的数值有点差异,但基本能满足用户使用。 /单精度浮点和双精度浮点主要差异在指数部分和尾数位数 /单精度(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) /尾数部分Mantis
5、sa(M): 52bit (b51-b0) /双精度的指数部分(E)采用的偏置码为1023(E-1023) 3 /转换原理:单精度浮点和双精度浮点符号位相同,将双精度的指数转换为单精度的指数,取双精度浮点数尾数部分52位的前23位作为单精度浮点数的尾数部分 /* /将流量计总量双精度浮点数按4个16位无符号整型(unsigned short)数据储存在LW10、LW11、LW12、LW13寄存器,计算后的单精度浮点数储存在LW16、LW17(顺序CDAB)。 macro_command main() bool bit48,ba8 /bit-原浮点数位;ba- short e2 /e-指数值 G
6、etData(bit0, “Local HMI“, LW_Bit, 1000, 48) /按位提取前48位,注意,每个字节提取的 16 位二进制数与需要的数相反,即:二进制数为 1111000001010101,排序1010101000001111,后16位舍弃 SetData(bit4, “Local HMI“, LW_Bit, 1400, 11) /将双精度浮点数指数部分按位储存到LW14寄存器 GetData(e0, “Local HMI“, LW, 14, 1) /读取双精度浮点数指数数值 /计算单精度浮点数指数 e1=e0-1023+127 SetData(e1, “Local HM
7、I“, LW, 15, 1) /将单精度浮点数指数数值写入LW15 寄存器 GetData(ba0, “Local HMI“, LW_Bit, 1500, 8) /按位读取单精度浮点数指数部分 /按位将单精度浮点数写入到LW16、LW17寄存器。LW16、LW17即为屏可以读取的float值(屏读取float值时,读取顺序是CDAB,所以AB写入LW17,CD写入LW16) SetData(bit45, “Local HMI“, LW_Bit, 1600, 3) SetData(bit16, “Local HMI“, LW_Bit, 1603, 16) SetData(bit0, “Local
8、 HMI“, LW_Bit, 1703, 4) SetData(ba0, “Local HMI“, LW_Bit, 1707, 8) SetData(bit15, “Local HMI“, LW_Bit, 1715, 1) end macro_command /位计算方法如下 /单精度浮点0=bit45 4 /单精度浮点1=bit46 /单精度浮点2=bit47 /单精度浮点3=bit16 /单精度浮点4=bit17 /单精度浮点5=bit18 /单精度浮点6=bit19 /单精度浮点7=bit20 /单精度浮点8=bit21 /单精度浮点9=bit22 /单精度浮点10=bit23 /单精度
9、浮点11=bit24 /单精度浮点12=bit25 /单精度浮点13=bit26 /单精度浮点14=bit27 /单精度浮点15=bit28 /单精度浮点16=bit29 /单精度浮点17=bit30 /单精度浮点18=bit31 /单精度浮点19=bit0 /单精度浮点20=bit1 /单精度浮点21=bit2 /单精度浮点22=bit3 /单精度浮点23=ba0 /单精度浮点24=ba1 /单精度浮点25=ba2 /单精度浮点26=ba3 /单精度浮点27=ba4 /单精度浮点28=ba5 /单精度浮点29=ba6 5 /单精度浮点30=ba7 /单精度浮点31=bit15 (原程序截图)
10、 6 以下为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) /转换原
11、理,流量计数据可忽略符号位,直接按指数位移位尾数,将尾数部分整数直接读出,小数部分计算储存为短整型 /* /将流量计总量双精度浮点数按4个16位无符号整型(unsigned short)数据储存在LW10、LW11、LW12、LW13寄存器,计算后的32位整数储存在LW20、LW21(顺序CDAB),小数储存在LW22。 macro_command main() bool bit64,a64,b32,c32,d32=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-
12、整理后整形位;d-整数位未用补0 short e18,xiao,dizhi2 /e-指数及指数偏置;xiao-小数计算值;dizhi-整数位写入地址 unsigned int zheng=0 /zheng-超出范围时整数写0 float guao /guao-小数位计算过渡值 GetData(bit0, “Local HMI“, LW_Bit, 1000, 64) /按位提取数据,注意,每个字节提取的16 位二进制数与需要的数相反,即:提取的二进制数为1111000001010101,实际值是1010101000001111 SetData(bit4, “Local HMI“, LW_Bit,
13、 1400, 11) /将双精度浮点数指数部分按位储存7 到LW14寄存器 GetData(e0, “Local HMI“, LW, 14, 1) /读取双精度浮点数指数数值 /计算单精度浮点数指数实际值及小数位偏置 e1=e0-1023 e2=e1+1 e3=e2+1 e4=e3+1 e5=e4+1 e6=e5+1 e7=e6+1 e8=e7+1 e9=e8+1 e10=e9+1 e11=e10+1 e12=e11+1 e13=e12+1 e14=e13+1 e15=e14+1 e16=e15+1 e17=e16+1 /计算尾数部分数值 a0=1 a1=bit3 a2=bit2 a3=bit
14、1 a4=bit0 a5=bit31 a6=bit30 a7=bit29 8 a8=bit28 a9=bit27 a10=bit26 a11=bit25 a12=bit24 a13=bit23 a14=bit22 a15=bit21 a16=bit20 a17=bit19 a18=bit18 a19=bit17 a20=bit16 a21=bit47 a22=bit46 a23=bit45 a24=bit44 a25=bit43 a26=bit42 a27=bit41 a28=bit40 a29=bit39 a30=bit38 a31=bit37 a32=bit36 a33=bit35 a34
15、=bit34 a35=bit33 a36=bit32 9 a37=bit63 a38=bit62 a39=bit61 a40=bit60 a41=bit59 a42=bit58 a43=bit57 a44=bit56 a45=bit55 a46=bit54 a47=bit53 a48=bit52 a49=bit51 a50=bit50 a51=bit49 a52=bit48 /计算整数位写入过渡地址(LB100-LB131) dizhi0=32-e2 /补0位数 dizhi1=100+dizhi0 /整数位开始地址 if e20 and e232 then /只计算整数在1-429496729
16、5 之间的值 SetData(d0, “Local HMI“, LB, 100, dizhi0) /空位补0 SetData(a0, “Local HMI“, LB, dizhi1, e2) /写入整数实际值 GetData(b0, “Local HMI“, LB, 100, 32) /取出整数位 /计算整型位实际值位排序 c0=b31 c1=b30 c2=b29 c3=b28 10 c4=b27 c5=b26 c6=b25 c7=b24 c8=b23 c9=b22 c10=b21 c11=b20 c12=b19 c13=b18 c14=b17 c15=b16 c16=b15 c17=b14
17、c18=b13 c19=b12 c20=b11 c21=b10 c22=b9 c23=b8 c24=b7 c25=b6 c26=b5 c27=b4 c28=b3 c29=b2 c30=b1 c31=b0 /计算小数部分数值 11 guao=ae2*0.5 /1位小数 guao=guao+ae3*0.25 /2位小数 guao=guao+ae4*0.125 /3位小数 guao=guao+ae5*0.0625 /4位小数 guao=guao+ae6*0.03125 /5位小数 guao=guao+ae7*0.015625 /6位小数 guao=guao+ae8*0.0078125 /7位小数 g
18、uao=guao+ae9*0.00390625 /8位小数 guao=guao+ae10*0.0001953125 /9位小数 guao=guao+ae11*0.00009765625 /10位小数 guao=guao+ae12*0.000048828125 /11位小数 guao=guao+ae13*0.0000244140625 /12位小数 guao=guao+ae14*0.00001220703125 /13位小数 guao=guao+ae15*0.000006103515625 /14位小数 guao=guao+ae16*0.0000030517578125 /15位小数 guao=
19、guao+ae17*0.00000152587890625 /16位小数 guao=guao*10000 /小数取4位整 xiao=guao /小数取4位 SetData(c0, “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 12 (原程序截图a) 13 (原程序截图b) 14 下面用
20、实际数计算看实际效果: 流量计总量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 15 浮点数转换器 (浮点数转换器截图) 浮点数转换器值为:578779.78053283691 手工计算 (浮点数转换器截图) 手工计算值:578779.77766265869140625