• 用JAVA实现插值查询的方法(算近似值,区间求法)


    插值查询:如果有这样一张表,有一列叫水位,有一列叫库容,比如下面的图。

    我现在想做这么一件事情:对于这个测站而言,当我输入某一个水位或者库容的时候,想要查询到对应的水位或者库容呢?

    而这个值不一定是存在数据库中的,也许这只是一个推导出来的近似值呢?

    算法要点:如果这个输入的值是位于数据库值的某一个区间内的话,那么取最小的区间,然后求这个区间内单位数量的值。

    大家听得可能有点不太明白,我画张图。

    呵呵,应该有点眉目了吧?这个第一步也是最重要的一步就是确定区间哦

    算法的话很简单,用一句公式来概括就是

    1.通过水位求库容:(单位水位所包含的库容)*(输入水位-这个水位左边区间的水位值)+这个水位左边区间的水位值

    2.通过库容求水位:(单位库容所包含的库容)*(输入库容-这个库容左边区间的库容值)+这个库容左边区间的库容值

    不废话,贴代码,用的是JAVA实现的

        //插值查询法
            @Override
            public String InterpolantQuery(ReservoirCapacityConditionParam param)
            {
                String finalVal="";
                float finalVolumn=0;
                StringBuffer sb=new StringBuffer();
                StringBuffer sd=new StringBuffer();
                sb.append("select z,v from hydro_curve_b where stcd='"+param.getStcd()+"' ");
                
                if(param.getV()==""&&param.getZ()!="")
                {
                    sb.append(" and z='"+param.getZ()+"'");
                }
                else if(param.getV()!=""&&param.getZ()=="")
                {
                    sb.append(" and v='"+param.getV()+"'");
                }
                
                List<Object []> fromSTCD=this.daoHelper.findBySql(sb.toString());
                
                //如果是已有数据,直接显示,否则算法查找
                /*算法:通过库容查水位或通过水位查库容,如果输入的值在已有数据的某个范围内,则定位此数据的最小范围
                 * 1.比如输入120,有119~121,118~122这2个范围,则取119~121这个近似范围
                 * 2.假设输入的是水位,要查询库容,那么首先算出每一米水位在(1)范围内的库容,然后算出库容的增量,用这个增量加上这个区间内较低的库容
                 * 3.由于框架不能使用TOP关键字,所以(1)的范围的的取法:左边:查出比输入值小的所有数据,按大小的降序拍了,取最后一条,右边:查出比输入值大的所有数据,按升序排列,取最后一条*/
                if(fromSTCD.size()==0)
                {
                    //如果水位为空,则按照库容查询水位
                    if(param.getZ()=="")
                    {
                    
                        if(param.getV().equals("0"))
                        {
                            //如果输入0,则不查询
                        }
                        
                        else
                        {
                            //查出左边区间的
                            List<Object []> left_fromSTCD=this.daoHelper.findBySql("select  z,v from hydro_curve_b where stcd='"+param.getStcd()+"' and v<'"+param.getV()+"' order by z asc");
    
                            //查出右边区间的
                            List<Object []> right_fromSTCD=this.daoHelper.findBySql("select  z,v from hydro_curve_b where stcd='"+param.getStcd()+"' and v>'"+param.getV()+"' order by z desc");
                            
                            float beginZ=0,beginV=0; //水位
                            float endZ=0,endV=0;     //库容
                            
                            //如果左边区间为空
                            if(left_fromSTCD.size()==0)
                            {
                                //重置左边的区间
                                left_fromSTCD=this.daoHelper.findBySql(" select z,min(v) v from hydro_curve_b where stcd='"+param.getStcd()+"' group by z order by z desc");
                                
                                for(Object []obj:left_fromSTCD)
                                {
                                    beginZ=Float.parseFloat(String.valueOf(obj[0]));
                                    beginV=Float.parseFloat(String.valueOf(obj[1]));
                                }
                                
                                //重置右边的区间
                                right_fromSTCD=this.daoHelper.findBySql("select z.* from (select  top 2 z,min(v) v from hydro_curve_b where stcd='"+param.getStcd()+"' and  v>"+param.getV()+" group by z) z order by z.z asc");
                                
                                for(Object []obj:right_fromSTCD)
                                {
                                    endZ=Float.parseFloat(String.valueOf(obj[0]));
                                    endV=Float.parseFloat(String.valueOf(obj[1]));
                                }
                            }
                            
                            else
                            {    
                                for(Object []obj:left_fromSTCD)
                                {
                                    beginZ=Float.parseFloat(String.valueOf(obj[0]));
                                    beginV=Float.parseFloat(String.valueOf(obj[1]));
                                }
                            }
                            
                            //如果右边区间为空
                            if(right_fromSTCD.size()==0)
                            {
                                //重置左边的区间
                                left_fromSTCD=this.daoHelper.findBySql("select z.* from (select  top 2 z,max(v) v from hydro_curve_b where stcd='"+param.getStcd()+"' and v<"+param.getV()+" group by z) z order by z.z desc");
                                
                                for(Object []obj:left_fromSTCD)
                                {
                                    beginZ=Float.parseFloat(String.valueOf(obj[0]));
                                    beginV=Float.parseFloat(String.valueOf(obj[1]));
                                }
                                
                                //重置右边的区间
                                right_fromSTCD=this.daoHelper.findBySql("select z,max(v) from hydro_curve_b where stcd='"+param.getStcd()+"' group by z order by z asc");
                                
                                for(Object []obj:right_fromSTCD)
                                {
                                    endZ=Float.parseFloat(String.valueOf(obj[0]));
                                    endV=Float.parseFloat(String.valueOf(obj[1]));
                                }
                            }
                            else
                            {    
                                for(Object []obj:right_fromSTCD)
                                {
                                    endZ=Float.parseFloat(String.valueOf(obj[0]));
                                    endV=Float.parseFloat(String.valueOf(obj[1]));
                                }
                            }
                    
                            //计算每一格库容所包含的水位
                            float eachVolumn=1/((endV-beginV)/(endZ-beginZ));
                            float z=Float.parseFloat(param.getV());
                            //得到最终的水位
                            finalVolumn=(z-beginV)*eachVolumn+beginZ;
                        }
                    
                    
                    
                    }
                    //如果库容为空,则按照水位查询库容
                    else if(param.getV()=="")
                    {
                        
                        if(param.getZ().equals("0"))
                        {
                            //如果输入0,则不做任何操作
                        }
                        else
                        {
                            //查出左边区间的
                            List<Object []> left_fromSTCD=this.daoHelper.findBySql("select  z,v from hydro_curve_b where stcd='"+param.getStcd()+"' and z<'"+param.getZ()+"' order by v asc");
    
                            //查出右边区间的
                            List<Object []> right_fromSTCD=this.daoHelper.findBySql("select  z,v from hydro_curve_b where stcd='"+param.getStcd()+"' and z>'"+param.getZ()+"' order by v desc");
                            
                            float beginZ=0,beginV=0; //水位,库容(left)
                            float endZ=0,endV=0;     //水位,库容(right)
                            
                            //如果输入的最小值比最数据库里的最小值小,那么取数据库里的最小值
                            //重置区间的原因是因为最小值是一个区间,用TOP2确定范围
                            if(left_fromSTCD.size()==0)
                            {
                                //重置左边的区间
                                left_fromSTCD=this.daoHelper.findBySql(" select MIN(z) z,v from hydro_curve_b where stcd='"+param.getStcd()+"' group by v order by v desc");
                                
                                for(Object []obj:left_fromSTCD)
                                {
                                    beginZ=Float.parseFloat(String.valueOf(obj[0]));
                                    beginV=Float.parseFloat(String.valueOf(obj[1]));
                                }
                                
                                //重置右边的区间
                                right_fromSTCD=this.daoHelper.findBySql("select z.* from (select  top 2 min(z) z,v from hydro_curve_b where stcd='"+param.getStcd()+"' and  z>"+param.getZ()+" group by v) z order by z.v asc");
                                
                                for(Object []obj:right_fromSTCD)
                                {
                                    endZ=Float.parseFloat(String.valueOf(obj[0]));
                                    endV=Float.parseFloat(String.valueOf(obj[1]));
                                }
                            }
                            else
                            {    
                    
                                for(Object []obj:left_fromSTCD)
                                {
                                    beginZ=Float.parseFloat(String.valueOf(obj[0]));
                                    beginV=Float.parseFloat(String.valueOf(obj[1]));
                                }
                            }
                            //如果输入的最大值比数据库里的最大值大,那么取数据库的最大值。
                            if(right_fromSTCD.size()==0)
                            {
                                
                                //重置左边的区间
                                left_fromSTCD=this.daoHelper.findBySql("select z.* from (select  top 2 max(z) z,v from hydro_curve_b where stcd='"+param.getStcd()+"' and z<"+param.getZ()+" group by v) z order by z.v desc");
                                
                                for(Object []obj:left_fromSTCD)
                                {
                                    beginZ=Float.parseFloat(String.valueOf(obj[0]));
                                    beginV=Float.parseFloat(String.valueOf(obj[1]));
                                }
                                
                                //重置右边的区间
                                right_fromSTCD=this.daoHelper.findBySql("select max(z) z,v from hydro_curve_b where stcd='"+param.getStcd()+"' group by v order by v asc");
                                
                                for(Object []obj:right_fromSTCD)
                                {
                                    endZ=Float.parseFloat(String.valueOf(obj[0]));
                                    endV=Float.parseFloat(String.valueOf(obj[1]));
                                }
    
                            }
                                
                            else
                            {    
                                for(Object []obj:right_fromSTCD)
                                {
                                    endZ=Float.parseFloat(String.valueOf(obj[0]));
                                    endV=Float.parseFloat(String.valueOf(obj[1]));
                                }
                            }
                            //计算每一格库容所包含的水位
                            //float eachVolumn=(endV-beginV)/(endZ-beginZ);
                            float eachVolumn=1/((endZ-beginZ)/(endV-beginV));
                            float z=Float.parseFloat(param.getZ());
                            //得到最终的库容
                            //finalVolumn=(endZ-z)*eachVolumn+endZ;
                            finalVolumn=beginV+eachVolumn*(z-beginZ);
                            
                        }
                        
                        
                    }
                            
                    return String.valueOf(finalVolumn);
        
                    
                }
                else
                {
                    for(Object obj[]:fromSTCD)
                    {
                        if(param.getV()=="")
                        {
                        finalVal=String.valueOf(obj[1]);
                        }
                        else if(param.getZ()=="")
                        {
                            finalVal=String.valueOf(obj[0]);
                        }
                        
                    }
                    return finalVal;
                }
                
                
            }

    其中也没什么难点,就是要注意一下左右区间重置的计算方法。

    因为每次FOR遍历出里面的变量以后,前面的变量都会被后面的变量所覆盖,所以这里大家需要注意一下,合理使用top关键字和order by 是做出这个的关键,

    好了,最后截图2张给大家看看效果,最后啰嗦一句,插值查询法虽然是算出来的,但是和数据库里的数据时息息相关的,是根据数据库里的数据算出的近似值。

    比如下面的图,都是输入200的水位,但是结果不同,因为他们对应的区间不同。

  • 相关阅读:
    SAP Cloud for Customer的Account Team里的role如何配置
    SAP标准培训课程C4C10学习笔记(二)第二单元
    SAP标准培训课程C4C10学习笔记(一)第一单元
    如何找到SAP Cloud for Customer标准培训和认证方面的信息
    我用ABAP做过的那些无聊的事情
    有道云笔记不需要通过开通会员的方式来去除广告显示
    微软OneDrive使用体验
    自己开发的在线视频下载工具,基于Java多线程
    CloudFoundry命令行和Kubernetes命令行的Restful API消费方式
    利用装饰器计算函数运行的时间
  • 原文地址:https://www.cnblogs.com/kmsfan/p/3946100.html
Copyright © 2020-2023  润新知