| | |
| | | package com.whyc.util; |
| | | |
| | | import com.whyc.dto.Response; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.text.DecimalFormat; |
| | | import java.text.ParseException; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * 计算工具类 |
| | |
| | | return (int) (res * 100) + "%"; |
| | | } |
| | | |
| | | /** |
| | | * 提取公共方法,相除获取比例,返回可选String或者Float |
| | | * @param type 1表示小数,2表示除去%的比例,3表示%的比例 |
| | | * @return Object String或者Float类型 |
| | | * */ |
| | | public static Object divide(Object num, Object num2, Integer type, Integer scale){ |
| | | Object res = 0; |
| | | double num2Double=Double.parseDouble(num2.toString()); |
| | | double numDouble=Double.parseDouble(num.toString()); |
| | | if(num2Double!=0){ |
| | | //0.05 |
| | | if (type == 1) { |
| | | res = BigDecimal.valueOf(numDouble).divide(BigDecimal.valueOf(num2Double), scale, RoundingMode.HALF_UP).floatValue(); |
| | | } |
| | | //5 |
| | | else { |
| | | BigDecimal multiply = BigDecimal.valueOf(numDouble).multiply(BigDecimal.valueOf(100)); |
| | | BigDecimal divide = multiply.divide(BigDecimal.valueOf(num2Double), scale, RoundingMode.HALF_UP); |
| | | if (type == 2) { |
| | | res = divide.floatValue()+""; |
| | | } |
| | | //5% |
| | | else{ |
| | | res = divide.floatValue()+"%"; |
| | | } |
| | | } |
| | | return res; |
| | | }else{ |
| | | if(type == 1){ |
| | | return 0.0; |
| | | }else{ |
| | | if(type==2){ |
| | | return "0"; |
| | | }else{ |
| | | return "0%"; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static float multiply(float num,float num2,int scale){ |
| | | return BigDecimal.valueOf(num).multiply(BigDecimal.valueOf(num2)).setScale(2,RoundingMode.HALF_UP).floatValue(); |
| | | } |
| | | |
| | | /** |
| | | * 求自变量X,因变量Y的线性回归 @PerryHsu |
| | | * y = ax+b |
| | | * |
| | | * a = ∑Yi(Xi-X的平均值)/∑(Xi^2)-1/n*(∑(Xi^2) |
| | | * |
| | | * b = 1/n*∑(Yi-aXi) |
| | | * |
| | | * */ |
| | | public static Response linearRegressionUnary(List<Double> listX, List<Double> listY,Double x) { |
| | | List<Double> resList = new LinkedList<>(); |
| | | |
| | | int sizeX = listX.size(); |
| | | int sizeY = listY.size(); |
| | | DecimalFormat df = new DecimalFormat("0.##"); |
| | | |
| | | if (sizeX != sizeY) { |
| | | return new Response<>().set(1,false,"分子分母数量不一致。"); |
| | | } |
| | | |
| | | Double sum = 0d; |
| | | for (Double xi : listX) { |
| | | sum += xi; |
| | | } |
| | | double avgX = sum/ sizeY; |
| | | |
| | | //a的分子 |
| | | double aMolecule = 0; |
| | | for (int i = 0; i < sizeX; i++) { |
| | | aMolecule += listY.get(i) * (listX.get(i) - avgX); |
| | | } |
| | | |
| | | //a的分母 |
| | | double aDenominator = 0; |
| | | int aDenominatorXi = 0; |
| | | for (int i = 0; i < sizeX; i++) { |
| | | aDenominator += Math.pow(listX.get(i), 2); |
| | | aDenominatorXi += listX.get(i); |
| | | } |
| | | aDenominator = aDenominator - (1.0 / sizeX) * (Math.pow(aDenominatorXi, 2)); |
| | | |
| | | //System.out.println("w_denominator:"+w_denominator+" w_denominator_xi:"+w_denominator_xi); |
| | | |
| | | double a = aMolecule / aDenominator; |
| | | |
| | | double b = 1.0 / sizeX; |
| | | double sumYAX = 0; |
| | | for (int i = 0; i < sizeX; i++) { |
| | | sumYAX += (listY.get(i) - a * listX.get(i)); |
| | | } |
| | | b = b * sumYAX; |
| | | |
| | | String symbol = "+"; |
| | | if (b < 0) { |
| | | symbol = ""; |
| | | } |
| | | //System.out.println("y=" + df.format(a) + "x" + symbol + df.format(b)); |
| | | |
| | | Double y = a*x + b; |
| | | resList.add(a); |
| | | resList.add(b); |
| | | resList.add(y); |
| | | return new Response().setII(1,true,resList,null); |
| | | } |
| | | |
| | | public static void main(String[] args) throws ParseException { |
| | | |
| | | /*List<Double> x = Arrays.asList(5d, 9d, 15d, 19d, 19d, 45d); |
| | | |
| | | List<Double> y = Arrays.asList(4d, 6d, 12d, 15d, 15d, 37d);*/ |
| | | //按照年为单位为x.变化差值为y |
| | | /*List<Double> x = Arrays.asList( |
| | | DateUtil.YYYY_MM_DD_HH_MM_SS.parse("2021-04-13 09:14:36").getTime()*1d, |
| | | DateUtil.YYYY_MM_DD_HH_MM_SS.parse("2021-10-14 13:46:36").getTime()*1d, |
| | | DateUtil.YYYY_MM_DD_HH_MM_SS.parse("2022-03-18 11:08:36").getTime()*1d, |
| | | DateUtil.YYYY_MM_DD_HH_MM_SS.parse("2022-03-18 13:56:36").getTime()*1d); |
| | | |
| | | List<Double> y = Arrays.asList( |
| | | 99d, |
| | | 80d, |
| | | 71.9d, |
| | | 71d);*/ |
| | | /*long time1 = DateUtil.YYYY_MM_DD_HH_MM_SS.parse("2021-04-13 09:14:36").getTime(); |
| | | long time2 = DateUtil.YYYY_MM_DD_HH_MM_SS.parse("2021-10-14 13:46:36").getTime(); |
| | | long time3 = DateUtil.YYYY_MM_DD_HH_MM_SS.parse("2022-03-18 11:08:36").getTime(); |
| | | long time4 = DateUtil.YYYY_MM_DD_HH_MM_SS.parse("2022-03-18 13:56:36").getTime(); |
| | | long time5 = DateUtil.YYYY_MM_DD_HH_MM_SS.parse("2023-03-12 13:56:36").getTime();*/ |
| | | long time1 = ThreadLocalUtil.parse("2021-04-13 09:14:36",1).getTime(); |
| | | long time2 = ThreadLocalUtil.parse("2021-10-14 13:46:36",1).getTime(); |
| | | long time3 = ThreadLocalUtil.parse("2022-03-18 11:08:36",1).getTime(); |
| | | long time4 = ThreadLocalUtil.parse("2022-03-18 13:56:36",1).getTime(); |
| | | long time5 = ThreadLocalUtil.parse("2023-03-12 13:56:36",1).getTime(); |
| | | |
| | | double c1 = 99d; |
| | | double c2 = 98d; |
| | | double c3 = 96.9d; |
| | | double c4 = 95d; |
| | | |
| | | List<Double> x = Arrays.asList( |
| | | 0d, |
| | | (time2-time1)*1d/1000/60/60/24, |
| | | (time3-time1)*1d/1000/60/60/24, |
| | | (time4-time1)*1d/1000/60/60/24 |
| | | ); |
| | | |
| | | |
| | | List<Double> y = Arrays.asList( |
| | | c1, |
| | | c2, |
| | | c3, |
| | | c4 |
| | | ); |
| | | double v = (time5 - time1) * 1d / 1000 / 60 / 60 /24; |
| | | System.out.println(v); |
| | | Response response = linearRegressionUnary(x, y, v); |
| | | System.out.println(response); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * |
| | | * @param startNum 起始数 -1 = limitStart ,因为limit是从0开始 |
| | | * @param endNum 终止数 |
| | | * @param pageSize 每页条数 |
| | | * @param queryCountMap key-年份,value-数量 |
| | | * @return {"2023",[2,20]} |
| | | * 表名,[limit 2,20] |
| | | */ |
| | | public static Map<String, List<Integer>> getQueryTableAndLimit(int startNum, int endNum, int pageSize, Map<String, Integer> queryCountMap) { |
| | | Map<String,List<Integer>> resultMap = new LinkedHashMap<>(); |
| | | //定位起始数,在哪个年份范围内,起始数值;终止数,在哪个年份范围内,终止数值 |
| | | Set<String> queryKeySet = queryCountMap.keySet(); |
| | | int sum = 0; |
| | | int lastSum = 0; |
| | | |
| | | String limitStartYear = null; |
| | | int limitStart = 0; |
| | | String limitEndYear = null; |
| | | int limitEndSize = pageSize; |
| | | boolean limitStartFinished = false; |
| | | for (String queryKey : queryKeySet) { |
| | | int queryCount = queryCountMap.get(queryKey); |
| | | sum+=queryCount; |
| | | if(!limitStartFinished) { |
| | | if (startNum <= sum) { |
| | | limitStart = startNum - lastSum; |
| | | limitStartYear = queryKey; |
| | | //完成了limit 起始值的获取,后续不需要继续执行 |
| | | limitStartFinished = true; |
| | | } |
| | | } |
| | | if(limitStartFinished) { //limit 起始值获取后,开始计算终止的记录数量 |
| | | if (endNum <= sum) { |
| | | limitEndYear = queryKey; |
| | | |
| | | break; |
| | | } |
| | | //首次,执行起始limit的时候, limitEndSize(记录预留的查询个数)需要减去limitStart占用的 |
| | | if(limitEndSize == pageSize){ |
| | | limitEndSize = pageSize - (sum - startNum + 1); |
| | | }else{ //如果还没达到 终止数值,需要减去本次查询消耗掉的数量 |
| | | limitEndSize = limitEndSize - queryCount; |
| | | } |
| | | } |
| | | |
| | | lastSum = sum; |
| | | } |
| | | |
| | | boolean limitStartCompareFlag = true; |
| | | boolean tableStartFlag = false; |
| | | for (String queryKey : queryKeySet) { |
| | | int queryCount = queryCountMap.get(queryKey); |
| | | if(queryKey.equals(limitStartYear) && limitStartCompareFlag){ |
| | | tableStartFlag = true; |
| | | //从这里开始,取记录数 |
| | | LinkedList<Integer> limitList = new LinkedList<>(); |
| | | if(queryKey.equals(limitEndYear)) { //同一年 |
| | | limitList.add(limitStart-1); |
| | | limitList.add(pageSize); |
| | | resultMap.put(queryKey,limitList); |
| | | break; |
| | | }else{ |
| | | limitList.add(limitStart-1); |
| | | limitList.add(queryCount); |
| | | resultMap.put(queryKey,limitList); |
| | | } |
| | | limitStartCompareFlag = false; |
| | | continue; |
| | | } |
| | | //不同年,继续 |
| | | if(tableStartFlag) { //已经经过了起始年,才可以取数据. 起始年前的数据无效 |
| | | if (queryKey.equals(limitEndYear)) { //找到终止年 |
| | | LinkedList<Integer> limitList = new LinkedList<>(); |
| | | limitList.add(0); |
| | | limitList.add(limitEndSize); |
| | | resultMap.put(queryKey, limitList); |
| | | break; |
| | | } else { //不是终止年,属于中间年 |
| | | LinkedList<Integer> limitList = new LinkedList<>(); |
| | | limitList.add(0); |
| | | limitList.add(queryCount); |
| | | resultMap.put(queryKey, limitList); |
| | | } |
| | | } |
| | | } |
| | | return resultMap; |
| | | |
| | | } |
| | | } |