TwinCAT3中REAL类型超32768后无法累加小数的问题咨询
TwinCAT3中REAL类型超过32768后无法累加小数值的原因与解决办法
问题复现
以下是触发问题的最简TwinCAT3代码:
// declaration fTest : REAL := 32700.0; // implementation fTest := fTest + 0.001;
运行后fTest会增长到32768,但此后累加0.001、0.0019或0.0011时数值不再变化,只有将增量改为0.002才能继续增长。
原因分析
这不是TwinCAT的BUG,而是32位REAL类型(符合IEC 61131-3/IEC 559/IEEE754标准)的固有精度限制:
- 32位REAL的结构为:1位符号位、8位偏移指数(实际指数范围-126~+127)、23位尾数。
- 当数值达到32768(即
2^15)时,该数值处于[2^15, 2^16)区间,此时REAL类型的**单位最后一位精度(ULP)**为2^(15-23) = 2^-8 = 0.00390625。 - 这意味着,该区间内的REAL数值只能以0.00390625为最小步长变化。任何小于该步长的增量(比如0.001、0.002)都会被浮点数的舍入机制丢弃,导致数值无法更新;只有当增量累计超过0.00390625时,才会触发数值变化。
解决办法
针对该问题,可采用以下几种方案:
- 改用更高精度的浮点类型:使用TwinCAT中的
LREAL(64位双精度浮点数),其尾数为52位,在32768数值下的ULP约为1.4e-11,远小于0.001,完全支持小数值的累加操作。只需将变量声明改为fTest : LREAL := 32700.0;即可。 - 分离基数与累加计数:用整数类型记录累加次数,最后再计算实际数值。例如:
// declaration nAccumCount : INT := 0; fBaseValue : REAL := 32700.0; // implementation nAccumCount := nAccumCount + 1; fTest := fBaseValue + nAccumCount * 0.001; - 使用定点数存储:将数值放大为整数(比如放大1000倍),用整数类型存储累加,需要时再转换为REAL:
// declaration iTest : DINT := 32700000; // 32700.0 * 1000 // implementation iTest := iTest + 1; // 对应累加0.001 fTest := iTest / 1000.0;
内容的提问来源于stack exchange,提问作者Pablo
相关产品推荐
相关产品推荐

