[西门子] 用 Kahan 算法解决西门子 TIA Portal 流量累加误差问题

[复制链接]
查看79 | 回复0 | 2024-6-16 12:02:31 | 显示全部楼层 |阅读模式
本帖最后由 工控老炮儿 于 2024-6-16 12:15 编辑

概述

浮点数计算产生误差一般有两个原因。

1.二进制小数位可能是一个无限位的小数。由于计算机内部以二进制保存,所以十进制的有限位小数,在计算机内部可能会是一个无限位二进制小数。例如:十进制的 0.1 虽然只有一位小数,但当转成二进制小数时则是无限循环小数 0.000 1100 1100 1100...

2.计算机保存浮点数的精度有限。

例如:数据类型 Real 最多可以精确到 6 位 (二进制 23 位)有效数字,数据类型 LReal 最多可以精确到 15 位(二进制 52 位)有效数字。如果指定的小数位数比数据类型可保存的位数要多,那么将根据该值范围所允许的精度值对该值进行四舍五入。

鉴于以上原因,当高阶浮点数和低阶浮点数进行运算时,例如:大数+小数时,如果小数超过精度范围,则将被忽略。如果在流量累加应用场景中则会导致累加值不准确。

浮点数加法实例

设计一个程序对 100000 个 0.1 进行累加计算。

1.首先用常规算法进行计算,为了代码简便,程序中使用了 FOR 循环。



图 1:100000 个 0.1 累加求和常规算法

在循环组织块 OB Main 中调用并在线监控计算结果。



图 2:100000 个 0.1 累加求和计算结果常规算法

从上图可以看到,得到的结果并不是我们所期望的 10000.0 ,而是得到结果 9998.557,偏差 1.443。

2.下面用 Kahan 算法进行计算,为了代码简便,程序中使用了 FOR 循环。



图 3:100000 个 0.1 累加求和 Kahan 算法

在循环组织块 OB Main 中调用并在线监控计算结果。



图 4:100000 个 0.1 累加求和计算结果 Kahan 算法

从上图可以看到,得到的结果正是我们所期望的 10000.0 ,无偏差。

设计 Kahan 加法计算器

根据 Kahan 算法设计一个加法计算器,Kahan 算法的原理是通过一个中间变量记录累计误差,当下次计算时,把累计误差补上,并且把累计误差更新到求和结果,如果累计误差值过小不能被正常累加上,则累加误差值将继续增加,等到达可以计算的精度后再累加。



图 5:Kahan 加法计算器

设计流量累加器

流量累加计算程序如下图。详细过程可翻阅以前文章,只是在前面文章的基础上增加了 Kahan 累加算法。



图 6:流量累加器程序

功能测试

测试时,为了提高效率,可以为流量累加值给定一个较大初始值,然后调小流量。



图 7:流量累加功能测试

可以看到,当流量调到如上图数值(很小的浮点数)后,流量 1 数值(常规算法)不再累加。流量 2 数值( Kahan 算法)继续累加。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册哦

x
您需要登录后才可以回帖 登录 | 注册哦

本版积分规则