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.*; /** * 计算工具类 */ public class MathUtil { public static final Integer TYPE_FLOAT = 1; public static final Integer TYPE_FLOAT_100 = 2; public static final Integer TYPE_FLOAT_PERCENT = 3; /** * 提取公共方法,相除获取比例,返回可选String或者Float * @param type 1表示小数,2表示除去%的比例,3表示%的比例 * @return Object String或者Float类型 * */ public static Object divide(Object num,Object num2,Integer type){ float res = 0; double num2Double=Double.parseDouble(num2.toString()); if(num2Double!=0){ if (num instanceof Integer) { res = BigDecimal.valueOf((Integer) num).divide(BigDecimal.valueOf((Integer) num2), 2, RoundingMode.HALF_UP).floatValue(); } if (num instanceof Float) { res = BigDecimal.valueOf((Float) num).divide(BigDecimal.valueOf((Float) num2), 2, RoundingMode.HALF_UP).floatValue(); } if (num instanceof Double) { res = BigDecimal.valueOf((Double) num).divide(BigDecimal.valueOf((Double) num2), 2, RoundingMode.HALF_UP).floatValue(); } } //0.05 if (type == 1) { return res; } //5 else if (type == 2) { return (int) (res * 100); } //5% 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 listX, List listY,Double x) { List 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 x = Arrays.asList(5d, 9d, 15d, 19d, 19d, 45d); List y = Arrays.asList(4d, 6d, 12d, 15d, 15d, 37d);*/ //按照年为单位为x.变化差值为y /*List 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 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 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 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> getQueryTableAndLimit(int startNum, int endNum, int pageSize, Map queryCountMap) { Map> resultMap = new LinkedHashMap<>(); //定位起始数,在哪个年份范围内,起始数值;终止数,在哪个年份范围内,终止数值 Set 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 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 limitList = new LinkedList<>(); limitList.add(0); limitList.add(limitEndSize); resultMap.put(queryKey, limitList); break; } else { //不是终止年,属于中间年 LinkedList limitList = new LinkedList<>(); limitList.add(0); limitList.add(queryCount); resultMap.put(queryKey, limitList); } } } return resultMap; } }