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<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;
|
}
|
}
|