仪表设计中的浮点数问题及解析

时间:2011-09-04

  引言

  C语言发展如此迅速,而且成为的语言之一,它既具有语言的特点,又具有汇编语言的特点。它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。因此,它的应用范围广泛,不仅仅是在软件开发上,而且各类科研都需要用到C语言,具体应用比如单片机以及嵌入式系统开发。

  1 问题

  所谓标准值是度比被测仪表高3~5倍的标准表测得的数值。仪表不仅和误差有关,而且和仪表的测量范围有关。误差大,相对百分误差就大,仪表度就低。如果误差相同的两台仪表,其测量范围不同,那么测量范围大的仪表相对百分误差就小,仪表度就高。度是仪表很重要的一个质量指标,常用等级来规范和表示。等级就是相对百分误差去掉正负号和%。利用相应的计算公式,Instant每秒累加便得累积量Cumulation。Cumulation的数据显示范围为0~99 999 999,超出后从零显示,使得Cumulation的小于0.3%。时刻刷新,显示数据范围为0.000 1~99 999,测量小于0.5%。

  程序编制完毕,在调试时发现下列问题:瞬时量测量高于指标要求,累积量在程序运行的开始阶段也满足要求,但随着测量时间的增长,累积量的实际测量值和理论计算值之间的差别越来越大,超过了技术指标的要求。若不加干涉任其运行,当时间足够长时,显示模块显示的数据不再发生变化,即流量计的累积量不再发生变化了,但此时瞬时量显示的数据依旧正确。某次测试时,通过设置流量计参数,使瞬时量理论值为3600 m3/h,以10min为一个测量周期进行测量,理论计算得累积量每个周期应累加600。实测数据如表1所列。

 

 a.JPG


   由表1中的数据可知,第1个测试周期满足要求,从第2个周期开始误差已经超过了技术指标要求,并且误差随着时间的增加而增大,在这种状态下流量计是无法正常工作的。那么问题出现在什么地方呢?经过查阅资料和仔细研读程序发现,在定义累积量和瞬时量时采用了如下形式:

  double Cumulation;

  float Instant;

  使用了编译器PICC 9.5的默认编译设置。查阅编译器的使用手册得知,HI-TECH公司的编译器PICC 9.5的浮点数采用IEEE754规范,一个float类型数据占24位,同时支持以24位、32位两种方式存储一个double型数据,但为了节约存储空间,在不对编译器选项修改的情况下,double型数据采用的也是24位。显然,在此默认情况下累积量的计算不能满足要求。

  通过修改编译器选项,使double型数据以32位格式存储,同时修改程序的其他相关地方后,重新进行测试。测试时通过设置流量计参数,使瞬时流量理论值为3600m3/h,以1个小时为一测量周期,显然累积量每小时的累积值理论上应为3600。实测数据如表2所列,测试开始时刻Cumulation等于50。

 

 b.JPG


  比较表1和表2的数据可知,修改效果十分明显,在同等的测量条件下仪表连续运行27小时后,累积量的测量仍然满足技术指标要求。但存在的问题也很明显,通过对比数据发现,累积量的测量误差是随着时间的增加而增加的。可以预见,当运行的时间足够长时测量误差终会突破技术指标的要求,实验结果确实也证明了这一点。

  经过研究发现,问题出现在处理累积量的方法上。在前面的程序中直接通过每秒执行语句“Cureulation=Cumulation+Instant;”来计算累积量。而参考文献明确告诉我们,两个浮点数相加时,其误差随着两个数差别的增大而增大,表2中误差的变化规律也证明了这一点。这是因为每次执行语句“Cumulation=Cumulation+Instant;”时,Instant是不变的,而Cumulation在不断增加。当两者大小相差的数量级足够大时,Instant与Cumulation相加会丢失Instant,致使流量计累积量读数不再发生变化,这也是前面调试时出现问题的原因。

  上述大数加小数丢失小数的情况在整数相加时是不存在的,同时,流量计在运行时当测量的瞬时流量小于下限流量时会当作干扰信号切除掉,累积量无需累加。实验数据表明,当瞬时流量在下限流量和上限流量限定的全量程范围内变化时,累积量小于4000时测量完全满足技术指标的要求。我们采用的办法是,将累积量分两部分来存储。为此,另定义一个unsigned long型变量HBCumu,每当Cumulation累加超过2000时执行下述操作:

  HBCumu=HBCumu+2000;

  Cumulation=Cumulation-2000;

  即每次将Cumulation中的2000转存到HBCumu中,由于计算HBCumu时采用的是整数相加,因此不存在问题。同时通过此种操作,可以把Cumulation和Instant的大小差别限定在一个合适的范围内,从而保证计算Cumulation时满足要求。在EEPROM中分别给HBCumu、Cumu-lation开辟有独立的存储单元,每个存储周期分别存储两者的值。当前累积量的真实值等于HBCumu和Cumulation的和,显示数据时先求两者的和再进行显示。采用新方法后,在与前述相同的测试条件下重新对流量计进行测试,实测数据如表3所列。测试开始时刻,流量计的初始读数为86。

 


 c.JPG

  比较表3和表2的数据可以看出,采用转存方法对累积量进行存储后,很好地解决了测量随时间增加而变差的问题。我们对累积量计数满99 999 999的前后阶段也进行了测试,实验结果表明,测量误差与表3中的误差一致,这表明在全量程范围内误差都稳定在一个令人满意的范围内。此种方法与利用汇编编程处理的方法相比,避免了利用汇编代码处理浮点数的繁琐工作,保持了C语言的高效性和代码的良好移植性。

  2 存储问题

  项目要求在流量计正常运行时能够随时设定液体的密度、流量系数等参数,并且这些参数小数点后数据的位数固定。比如密度设定值,数据设定范围为0.001~999.999,小数点后固定为3位数据。程序编制完毕在调试阶段发现的问题是,当把参数设置完毕存入EEPROM、再读出来时,读出的数据和存入的数据并不一致。比如设定密度值为123.456,设定完毕存入EEPROM,然后读出来的数据是形如123.454这样的数据。

  针对这个问题的处理办法是,定义dEn为unsigned long型的数据,其中存放的数据是密度实际设定值放大1000倍后的数据,在程序其他地方用到密度设定值时,只需要将其除以1000得到真实值即可。这样在参数设定完毕存入。EEPROM及从EEPROM中读出数据时,实际上都是以整数形式进行操作的,这样就可以保证数据的正确性。为了给操作者一种仍旧是在设定一个小数点后有3位小数的参数的感觉,在设定和显示参数过程中,始终点亮LCM141相关数据位的小数点。

   关于浮点数

  浮点数是属于有理数中某特定子集的数的数字表示,在计算机中用以近似表示任意某个实数。具体的说,这个实数由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是2)的整数次幂得到,这种表示方法类似于基数为10的科学记数法。


  
上一篇:LED照明PWM调光技术
下一篇:简述面向绿色无线通信的体系结构

免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

相关技术资料