从数据点位置的查找方法,体验算法的强大力量(二分法)

在优化录波软件PLC-Recorder的离线分析软件ANA时,采用了常用的二分法替代掉原来的逐点搜索,运算时间从上百微秒锐减到数微秒。

运算过程:当用户点击了曲线时,软件会根据点坐标转换成X轴坐标,然后再去查询点的序号,来获得各条曲线的Y值。原算法会从上次点击的位置开始逐点搜索到新的点击位置。现在采用了二分法,直接从两头开始搜索,简单粗暴,但是效率奇高,看截屏:

1、原算法从原始数组直接搜索时的耗时情况:

当光标在右侧,再点击左侧时,调用了3次,分别是21us、79us、107us

 

 

2、原算法从曲线的点集合直接搜索时的耗时情况:

当光标在右侧,再点击左侧时,调用了2次,分别是47us、142us

3、二分法从原始数组直接搜索时的耗时情况:

当光标在右侧,再点击左侧时,调用了3次,分别是2us、1us、0us

4、二分法从曲线点集合搜索时的耗时情况:

当光标在右侧,再点击左侧时,调用了3次,分别是3us、3us、9us

 5、点集合的搜索程序:

 

 //method=0:查询左侧的点,1:查询右侧的点,2:查询最近的点
            long tstart = Global.sw.ElapsedTicks;
            Int32 left, right, center, result;
            bool Exact = false ;
            
            if (checkSeries)
            {                
                Series series1 =c.series;

                if (series1.Points.Count == 0)
                {
                    result = 0;
                }
                else
                {
                    left = 0;right = series1.Points.Count-1;
                    if((xValue - series1.Points[right].XValue) >= 0)//在右侧区域
                    {
                        result = right;
                        Exact = xValue== series1.Points[right].XValue;
                    }
                    else if((xValue -series1.Points[left].XValue) <= 0)//在左侧区域
                    {
                        result = left;
                        Exact = xValue == series1.Points[left].XValue;
                    }
                    else
                    {
                        while (true)
                        {
                            if (right - left <= 1)//两个点相邻或者重叠了
                            {
                                if (xValue == series1.Points[left].XValue)
                                {
                                    result = left; Exact = true;
                                }
                                else if (xValue == series1.Points[right].XValue)
                                {
                                    result = right; Exact = true;
                                }
                                else
                                {
                                    switch (method)
                                    {
                                        case 0:
                                            result = left;
                                            Exact = xValue == series1.Points[left].XValue;
                                            break;
                                        case 1:
                                            result = right;
                                            Exact = xValue == series1.Points[right].XValue;
                                            break;
                                        case 2:
                                            if ((xValue - series1.Points[left].XValue) <= (series1.Points[right].XValue - xValue))
                                            {
                                                result = left;
                                                Exact = xValue == series1.Points[left].XValue;
                                            }
                                            else
                                            {
                                                result = right;
                                                Exact = xValue == series1.Points[right].XValue;
                                            }
                                            break;
                                        default:
                                            result = left;
                                            Exact = xValue == series1.Points[left].XValue;
                                            break;
                                    }
                                }
                                break;
                            }
                            else
                            {
                                center = (left + right) / 2;
                                if (series1.Points[center].XValue <= xValue)
                                {
                                    left = center;
                                }
                                else
                                {
                                    right = center;
                                }
                            }
                        }
                    }
                }
               
            }//从曲线的数据点中进行搜索

小结

合理的算法是软件性能的保证。1、二分法可以大大减少搜索的次数,数据越多,优势越明显;2、数组还是比点集合的速度要快很多。

非常感谢好朋友thj的建议。

2020年12月13日


PLC-Recorder是一个纯国产的专业数据采集和记录小软件,可以进行PLC数据的连续记录、协助故障追踪、协助调试等功能。目前支持:西门子S7全系列、三菱、欧姆龙、基恩士、倍福、罗克韦尔(AB)、施耐德、松下、所有符合Modbus-TCP协议的国内外PLC及I/O设备(汇川、信捷、台达等)。欢迎广大工控朋友去官网下载试用(免费版的功能强大)!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值