From 29f4658d91d023377912055de7104476f25fd309 Mon Sep 17 00:00:00 2001 From: yangzhe123 <2824096059@qq.com> Date: Tue, 18 Nov 2025 16:26:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=9E=E5=BD=92=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/gunshi/project/hsz/datasync/Main.java | 10 +- .../controller/ForecastResultsController.java | 2 +- .../project/hsz/model/RegressionEquation.java | 40 ++++- .../hsz/service/ForecastResultsService.java | 144 ++++++++---------- .../project/hsz/service/JcskSyRService.java | 27 +++- .../hsz/service/SyDataCheckRuleService.java | 6 + .../project/hsz/timetask/PaDataTask.java | 26 ++-- .../project/hsz/util/RegressionAnalysis.java | 144 +++++++++--------- 8 files changed, 219 insertions(+), 180 deletions(-) diff --git a/service-datasync/src/main/java/com/gunshi/project/hsz/datasync/Main.java b/service-datasync/src/main/java/com/gunshi/project/hsz/datasync/Main.java index 81eb042..89a6ea0 100644 --- a/service-datasync/src/main/java/com/gunshi/project/hsz/datasync/Main.java +++ b/service-datasync/src/main/java/com/gunshi/project/hsz/datasync/Main.java @@ -11,12 +11,12 @@ import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling @MapperScan({ - "com.gunshi.project.hsz.datasync.mapper", - "com.gunshi.project.hsz.datasync.mapper.jcsk", - "com.gunshi.project.hsz.datasync.rsvrWaterLevel", + "com.gunshi.project.hsz.datasync.config", + "com.gunshi.project.hsz.datasync.flow", + "com.gunshi.project.hsz.datasync.gnss", "com.gunshi.project.hsz.datasync.rainfall", - "com.gunshi.project.hsz.datasync.gate", - "com.gunshi.project.hsz.datasync.riverWaterLevel", + "com.gunshi.project.hsz.datasync.seepage", + "com.gunshi.project.hsz.datasync.waterLevel", }) public class Main { diff --git a/src/main/java/com/gunshi/project/hsz/controller/ForecastResultsController.java b/src/main/java/com/gunshi/project/hsz/controller/ForecastResultsController.java index 2df35d7..5c74b78 100644 --- a/src/main/java/com/gunshi/project/hsz/controller/ForecastResultsController.java +++ b/src/main/java/com/gunshi/project/hsz/controller/ForecastResultsController.java @@ -102,7 +102,7 @@ public class ForecastResultsController { //收集实际数据和 List collect = voList.stream().filter(o -> { - return o.getYcRkQValue() != null; + return o.getRealRkQValue() != null; }).collect(Collectors.toList()); BigDecimal rkVValue = BigDecimal.ZERO; for (ForecastResultVo entity : collect) { diff --git a/src/main/java/com/gunshi/project/hsz/model/RegressionEquation.java b/src/main/java/com/gunshi/project/hsz/model/RegressionEquation.java index c9de141..48900f5 100644 --- a/src/main/java/com/gunshi/project/hsz/model/RegressionEquation.java +++ b/src/main/java/com/gunshi/project/hsz/model/RegressionEquation.java @@ -3,6 +3,7 @@ package com.gunshi.project.hsz.model; import lombok.Data; import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.List; /** @@ -45,7 +46,7 @@ public class RegressionEquation { } /** - * 生成方程字符串 + * 生成方程字符串(使用数学符号) */ private String generateEquationString() { StringBuilder sb = new StringBuilder("y = "); @@ -64,18 +65,19 @@ public class RegressionEquation { coeff = coeff.abs(); } - // 系数和变量 + // 系数和变量 - 保留至少20位小数 if (i == 0) { - // 常数项 - sb.append(String.format("%.4f", coeff)); + // 常数项 - 保留至少20位小数 + sb.append(coeff.setScale(20, RoundingMode.HALF_UP).toPlainString()); } else { - // 非常数项 + // 非常数项 - 保留至少20位小数 if (coeff.compareTo(BigDecimal.ONE) != 0 && coeff.compareTo(BigDecimal.ONE.negate()) != 0) { - sb.append(String.format("%.4f", coeff)); + sb.append(coeff.setScale(20, RoundingMode.HALF_UP).toPlainString()); } sb.append("x"); if (i > 1) { - sb.append("^").append(i); + // 使用Unicode上标数字 + sb.append(getSuperscript(i)); } } } @@ -83,6 +85,30 @@ public class RegressionEquation { return sb.toString(); } + /** + * 获取数字的Unicode上标表示 + */ + private String getSuperscript(int number) { + String numStr = String.valueOf(number); + StringBuilder superscript = new StringBuilder(); + for (char c : numStr.toCharArray()) { + switch (c) { + case '0': superscript.append('⁰'); break; + case '1': superscript.append('¹'); break; + case '2': superscript.append('²'); break; + case '3': superscript.append('³'); break; + case '4': superscript.append('⁴'); break; + case '5': superscript.append('⁵'); break; + case '6': superscript.append('⁶'); break; + case '7': superscript.append('⁷'); break; + case '8': superscript.append('⁸'); break; + case '9': superscript.append('⁹'); break; + default: superscript.append(c); + } + } + return superscript.toString(); + } + /** * 根据x值预测y值 */ diff --git a/src/main/java/com/gunshi/project/hsz/service/ForecastResultsService.java b/src/main/java/com/gunshi/project/hsz/service/ForecastResultsService.java index 9c7da1a..c7bc5e4 100644 --- a/src/main/java/com/gunshi/project/hsz/service/ForecastResultsService.java +++ b/src/main/java/com/gunshi/project/hsz/service/ForecastResultsService.java @@ -28,8 +28,6 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -42,7 +40,8 @@ import java.util.stream.Collectors; @Service @Slf4j @Transactional(rollbackFor = Exception.class) -public class ForecastResultsService extends ServiceImpl { +public class ForecastResultsService extends ServiceImpl +{ private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @@ -86,8 +85,8 @@ public class ForecastResultsService extends ServiceImpl * @auther: cxw * @date: 2024-07-30, 周二, 14:40:45 @@ -99,8 +98,8 @@ public class ForecastResultsService extends ServiceImpl * @auther: cxw * @date: 2024-07-31, 周三, 11:09:24 @@ -124,19 +123,9 @@ public class ForecastResultsService extends ServiceImpl * @auther: cxw * @date: 2024-08-05, 周一, 17:14:52 @@ -160,8 +149,6 @@ public class ForecastResultsService extends ServiceImpl pptnRAllList = new ArrayList<>(); List pptnRFutureList = new ArrayList<>(); @@ -196,7 +183,7 @@ public class ForecastResultsService extends ServiceImpl zvarlBS = stZvarlBService.list(new QueryWrapper().eq("stcd", attResBase.getStcd()).orderBy(true, true, "rz")); // 水位历史数据 List rsvrRRealList = stRsvrRService.list(new QueryWrapper().eq("stcd", attResBase.getStcd()).ge("tm", startTime).le("tm", endTime)); - //TODO 将过五分数据转为整点数据 - rsvrRRealList.stream().forEach(o -> { - // 转换为 Instant 操作后再转回 Date - o.setTm(deleteMinites(o.getTm(), 5)); - }); List resultList = reorganizeRsvrRData(rsvrRRealList, dt); List periods = splitByDay8To8(startTime, endTime); // v:累计降雨 @@ -334,14 +316,14 @@ public class ForecastResultsService extends ServiceImpl= 0; i--) { int index = lastRArr.size() - 1 - (voList.size() - 1 - i); lastRArr.set(index, voList.get(i).getR().doubleValue()); - if (index <= 0) { + if(index <= 0){ break; } } // 预测执行 List forecastVoList = RrainfallForecast.getData(sdf.format(period[0]), forecastPa.getK().doubleValue(), forecastPa.getPa0().doubleValue(), Wm, forecastPa.getPt0().doubleValue(), H1, dt, - forecastPa.getPa().doubleValue(), PList, u, attResBase.getStcd(), qOther, vSum.doubleValue(), Rsum.doubleValue(), lastRArr); + forecastPa.getPa().doubleValue(), PList, u, attResBase.getStcd(), qOther, vSum.doubleValue(), Rsum.doubleValue(), lastRArr); if (CollectionUtils.isNotEmpty(forecastVoList)) { // 筛选同时段的真实水位数据 List realRsvrList = resultList.stream().filter(item -> item.getTm().compareTo(period[0]) >= 0 && item.getTm().compareTo(period[1]) <= 0).collect(Collectors.toList()); @@ -422,6 +404,7 @@ public class ForecastResultsService extends ServiceImpl> excuteForecastDebug(ForecastTask forecastTask) throws Exception { List voList = new ArrayList<>(); // 获取配置参数 @@ -475,7 +458,7 @@ public class ForecastResultsService extends ServiceImpl= 0; i--) { int index = lastRArr.size() - 1 - (voList.size() - 1 - i); lastRArr.set(index, voList.get(i).getR().doubleValue()); - if (index <= 0) { + if(index <= 0){ break; } } // 预测执行 - Map map = new HashMap<>(); + Map map = new HashMap<>(); map.put("in period" + k, sdf.format(period[0])); map.put("in K" + k, forecastPa.getK().doubleValue()); map.put("in pa0" + k, forecastPa.getPa0().doubleValue()); @@ -632,7 +615,7 @@ public class ForecastResultsService extends ServiceImpl forecastVoList = RrainfallForecast.getData(sdf.format(period[0]), forecastPa.getK().doubleValue(), forecastPa.getPa0().doubleValue(), Wm, forecastPa.getPt0().doubleValue(), H1, dt, - forecastPa.getPa().doubleValue(), PList, u, attResBase.getStcd(), qOther, vSum.doubleValue(), Rsum.doubleValue(), lastRArr); + forecastPa.getPa().doubleValue(), PList, u, attResBase.getStcd(), qOther, vSum.doubleValue(), Rsum.doubleValue(), lastRArr); map.put("out res" + k, forecastVoList); res.add(map); if (CollectionUtils.isNotEmpty(forecastVoList)) { @@ -715,24 +698,24 @@ public class ForecastResultsService extends ServiceImpl zvarlBS, ForecastResultVo resultVo, BigDecimal rz) { - if (CollectionUtils.isNotEmpty(zvarlBS)) { + private void calculateCap(List zvarlBS, ForecastResultVo resultVo, BigDecimal rz){ + if(CollectionUtils.isNotEmpty(zvarlBS)){ BigDecimal maxRz = zvarlBS.stream().max(Comparator.comparing(StZvarlB::getRz)).get().getRz(); BigDecimal minRz = zvarlBS.stream().min(Comparator.comparing(StZvarlB::getRz)).get().getRz(); - if (rz.compareTo(minRz) < 0 || rz.compareTo(maxRz) > 0) { + if(rz.compareTo(minRz) < 0 || rz.compareTo(maxRz) > 0){ return; } Map stZvalMap = zvarlBS.stream().collect(Collectors.toMap(StZvarlB::getRz, StZvarlB::getW, (existing, replacement) -> existing)); List list = zvarlBS.stream().map(StZvarlB::getRz).sorted().collect(Collectors.toList()); - resultVo.setNowCap(DataHandleUtil.calcData(rz, stZvalMap, list)); + resultVo.setNowCap(DataHandleUtil.calcData(rz,stZvalMap,list)); } } @@ -764,7 +747,7 @@ public class ForecastResultsService extends ServiceImpl gribList = forecastService.getGribData(tm, false); - if (CollectionUtils.isEmpty(gribList)) { + if(CollectionUtils.isEmpty(gribList)){ return pptnRFutureList; } //24小时每个网格的总量 @@ -797,9 +780,9 @@ public class ForecastResultsService extends ServiceImpl * @auther: cxw */ @@ -854,13 +837,13 @@ public class ForecastResultsService extends ServiceImpl * @auther: cxw */ @@ -868,9 +851,9 @@ public class ForecastResultsService extends ServiceImpl { - Date date = entity.getTm(); - return date.getMinutes() == 0 && date.getSeconds() == 0; - }).collect(Collectors.toMap( + Date date = entity.getTm(); + return date.getMinutes() == 0 && date.getSeconds() == 0; + }).collect(Collectors.toMap( e -> e.getStcd() + "_" + e.getTm(), // 使用属性组合作为键 Function.identity(), (existing, replacement) -> existing // 如果有冲突,保留现有的 @@ -886,7 +869,7 @@ public class ForecastResultsService extends ServiceImpl= 0 && !isHaveFuturePPtn) { + if(dataTm.compareTo(nowHourTime) >= 0 && !isHaveFuturePPtn){ break; } // 时间加1小时,得到应该拆数据的时间,后面往前推 @@ -925,7 +908,7 @@ public class ForecastResultsService extends ServiceImpl + * @return: java.util.List * @auther: cxw */ public static List splitByDay8To8(Date startDate, Date endDate) { @@ -1011,21 +994,21 @@ public class ForecastResultsService extends ServiceImpl paramMap = forecastUseparamService.getMap(new QueryWrapper().eq("param_code", "dt")); - if (paramMap != null) { + if(paramMap != null){ BigDecimal dt = new BigDecimal(paramMap.get("param_value").toString());// 时间间隔:小时h BigDecimal ycMaxSwH = BigDecimal.ZERO;// 预报最高调洪水位 BigDecimal ycMaxRkQ = BigDecimal.ZERO;// 预报最大入库流量 BigDecimal ycMaxCkQ = BigDecimal.ZERO;// 预报最大下泄流量 BigDecimal ycSumRkQ = BigDecimal.ZERO;// 预报入库流量累计和 - for (ForecastResultVo vo : forecastProject.getVoList()) { + for (ForecastResultVo vo : forecastProject.getVoList()){ BigDecimal ycSwHValue = vo.getYcSwHValue(); if (ycSwHValue.compareTo(ycMaxSwH) > 0) { ycMaxSwH = ycSwHValue; @@ -1053,7 +1036,7 @@ public class ForecastResultsService extends ServiceImpl 0 || dh.compareTo(BigDecimal.valueOf(y2 - y1)) > 0) { + if(dw.compareTo(BigDecimal.valueOf(x2 - x1)) > 0 || dh.compareTo(BigDecimal.valueOf(y2 - y1)) > 0){ throw new IllegalArgumentException("Geom参数区域范围不足预测降雨网格最小单位!!!"); } // 校验数据是否在最大允许范围(预测降雨所划定区域) @@ -1203,12 +1186,12 @@ public class ForecastResultsService extends ServiceImpl { @Autowired private SyRegressionDataService syRegressionDataService; + @Autowired + private SyDataCheckRuleService syDataCheckRuleService; + public Page pageQuery(JcskSyRPageSo page) { @@ -824,6 +824,9 @@ public class JcskSyRService extends ServiceImpl { //组合成为 时间 库水位 管道水位的数据 List data = new ArrayList<>(); for (JcskSyREightAm eightAm : jcskSyREightAms) { + if(eightAm.getMstm() == null || eightAm.getSpprwl() == null){ + continue; + } OsmoticPressDetailVo detailVo = new OsmoticPressDetailVo(); // 设置监测时间和监测值(管道水位) @@ -833,7 +836,23 @@ public class JcskSyRService extends ServiceImpl { // 查找对应的库水位 BigDecimal rzValue = findClosestRzValue(rzMap, mstmStr); + if(rzValue == null){ + continue; + } detailVo.setRz(rzValue); + //获取数据清洗规则 + SyDataCheckRule rule = syDataCheckRuleService.getByDvcd(dto.getDvcd()); + if(rule != null && rule.getIsAvailable() == 1){ + //校验这条数据是否符合规则 + if(rzValue.compareTo(rule.getRz()) >=0){ + //如果当前库水位大于等于设置库水位,则跳过这条数据 + continue; + } + if(eightAm.getSpprwl().compareTo(rule.getSyValue()) <=0){ + //如果当前监测值小于等于设置值,则跳过这套数据 + continue; + } + } data.add(detailVo); } if(data.isEmpty()){ diff --git a/src/main/java/com/gunshi/project/hsz/service/SyDataCheckRuleService.java b/src/main/java/com/gunshi/project/hsz/service/SyDataCheckRuleService.java index 359f993..d8853d5 100644 --- a/src/main/java/com/gunshi/project/hsz/service/SyDataCheckRuleService.java +++ b/src/main/java/com/gunshi/project/hsz/service/SyDataCheckRuleService.java @@ -51,4 +51,10 @@ public class SyDataCheckRuleService extends ServiceImpl queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SyDataCheckRule::getDvcd,dvcd); + return this.baseMapper.selectOne(queryWrapper); + } } diff --git a/src/main/java/com/gunshi/project/hsz/timetask/PaDataTask.java b/src/main/java/com/gunshi/project/hsz/timetask/PaDataTask.java index 9174402..e20319d 100644 --- a/src/main/java/com/gunshi/project/hsz/timetask/PaDataTask.java +++ b/src/main/java/com/gunshi/project/hsz/timetask/PaDataTask.java @@ -103,19 +103,19 @@ public class PaDataTask { forecastPaService.remove(new QueryWrapper().eq("tm", sdfDay.format(nowTime)).eq("stcd", attResBase.getResCode())); // 获取最新pa ForecastPa forecastPaLast = forecastPaService.getOne(new QueryWrapper().eq("stcd", skStcd).orderBy(true, false, "tm").last("limit 1")); - // 补数据时解开 -// if(ObjectUtils.isEmpty(forecastPaLast)){ -// forecastPaLast = new ForecastPa(); -// forecastPaLast.setStcd(skStcd); -// forecastPaLast.setTm("2024-01-01"); -// forecastPaLast.setK(new BigDecimal(0.97)); -// forecastPaLast.setPa0(BigDecimal.ZERO); -// forecastPaLast.setIm(new BigDecimal(120)); -// forecastPaLast.setPt0(BigDecimal.ZERO); -// forecastPaLast.setPa(BigDecimal.ZERO); -// forecastPaLast.setChtm(new Date()); -// -// } +// 补数据时解开 + if(ObjectUtils.isEmpty(forecastPaLast)){ + forecastPaLast = new ForecastPa(); + forecastPaLast.setStcd(skStcd); + forecastPaLast.setTm("2024-01-01"); + forecastPaLast.setK(new BigDecimal(0.97)); + forecastPaLast.setPa0(BigDecimal.ZERO); + forecastPaLast.setIm(new BigDecimal(120)); + forecastPaLast.setPt0(BigDecimal.ZERO); + forecastPaLast.setPa(BigDecimal.ZERO); + forecastPaLast.setChtm(new Date()); + + } if (CollectionUtils.isNotEmpty(paramList) && CollectionUtils.isNotEmpty(kList) && ObjectUtils.isNotEmpty(forecastPaLast) && !forecastPaLast.getTm().equals(sdfDay.format(nowTime))) { Calendar calendar2 = Calendar.getInstance(); calendar2.setTime(sdfDay.parse(forecastPaLast.getTm())); diff --git a/src/main/java/com/gunshi/project/hsz/util/RegressionAnalysis.java b/src/main/java/com/gunshi/project/hsz/util/RegressionAnalysis.java index 5843835..8f940a4 100644 --- a/src/main/java/com/gunshi/project/hsz/util/RegressionAnalysis.java +++ b/src/main/java/com/gunshi/project/hsz/util/RegressionAnalysis.java @@ -435,8 +435,8 @@ public class RegressionAnalysis { } private static BigDecimal calculateDeterminant3x3(BigDecimal a11, BigDecimal a12, BigDecimal a13, - BigDecimal a21, BigDecimal a22, BigDecimal a23, - BigDecimal a31, BigDecimal a32, BigDecimal a33) { + BigDecimal a21, BigDecimal a22, BigDecimal a23, + BigDecimal a31, BigDecimal a32, BigDecimal a33) { return a11.multiply(a22.multiply(a33).subtract(a23.multiply(a32))) .subtract(a12.multiply(a21.multiply(a33).subtract(a23.multiply(a31)))) .add(a13.multiply(a21.multiply(a32).subtract(a22.multiply(a31)))); @@ -584,6 +584,7 @@ public class RegressionAnalysis { return calculateCubic(data); } } + /** * 将中心化四次系数转换回原始坐标 */ @@ -620,75 +621,6 @@ public class RegressionAnalysis { return new BigDecimal[]{A, B, C, D, E}; } - /** - * 改进的线性方程组求解器(部分主元高斯消元) - * 用于解决n元一次方程组 Ax = b - */ - private static BigDecimal[] solveLinearSystemImproved(BigDecimal[][] matrix, BigDecimal[] vector) { - int n = vector.length; - - // 复制矩阵和向量(避免修改原数据) - BigDecimal[][] a = new BigDecimal[n][n]; - BigDecimal[] b = new BigDecimal[n]; - for (int i = 0; i < n; i++) { - a[i] = matrix[i].clone(); - b[i] = vector[i]; - } - - // 部分主元高斯消元:逐行处理,选择当前列的最大绝对值元素作为主元 - for (int k = 0; k < n; k++) { - // 找到当前列(k列)中绝对值最大的行(maxRow) - int maxRow = k; - BigDecimal maxVal = a[k][k].abs(); // 初始为当前对角线元素 - for (int i = k + 1; i < n; i++) { - BigDecimal current = a[i][k].abs(); - if (current.compareTo(maxVal) > 0) { - maxVal = current; - maxRow = i; - } - } - - // 交换行(将最大主元所在行交换到当前行k) - if (maxRow != k) { - BigDecimal[] tempRow = a[k]; - a[k] = a[maxRow]; - a[maxRow] = tempRow; - - BigDecimal tempB = b[k]; - b[k] = b[maxRow]; - b[maxRow] = tempB; - } - - // 检查主元是否为0(矩阵奇异) - if (a[k][k].compareTo(BigDecimal.ZERO) == 0) { - return null; - } - - // 消元:将第k列下方的元素消为0 - for (int i = k + 1; i < n; i++) { - BigDecimal factor = a[i][k].divide(a[k][k], MathContext.DECIMAL128); // 除法保留高精度 - for (int j = k; j < n; j++) { - a[i][j] = a[i][j].subtract(factor.multiply(a[k][j], MathContext.DECIMAL128), MathContext.DECIMAL128); - } - b[i] = b[i].subtract(factor.multiply(b[k], MathContext.DECIMAL128), MathContext.DECIMAL128); - } - } - - // 回代:从最后一行开始,依次求解每个变量 - BigDecimal[] x = new BigDecimal[n]; - for (int i = n - 1; i >= 0; i--) { - BigDecimal sum = BigDecimal.ZERO; - for (int j = i + 1; j < n; j++) { - sum = sum.add(a[i][j].multiply(x[j], MathContext.DECIMAL128), MathContext.DECIMAL128); - } - x[i] = b[i].subtract(sum, MathContext.DECIMAL128) - .divide(a[i][i], MathContext.DECIMAL128); // 除法保留高精度 - } - - return x; - } - - /** * 计算R² @@ -717,7 +649,6 @@ public class RegressionAnalysis { return BigDecimal.ONE.subtract(ssRes.divide(ssTot, MathContext.DECIMAL128), MathContext.DECIMAL128); } - /** * 检查所有数据点的x值是否相同 */ @@ -744,4 +675,73 @@ public class RegressionAnalysis { return sum.divide(new BigDecimal(data.size()), MathContext.DECIMAL128); } + /** + * 生成回归方程字符串(使用数学符号表示) + */ + public static String generateEquationString(int order, List coefficients) { + StringBuilder sb = new StringBuilder("y = "); + + for (int i = 0; i < coefficients.size(); i++) { + BigDecimal coeff = coefficients.get(i); + if (coeff.compareTo(BigDecimal.ZERO) == 0) { + continue; + } + + // 处理符号 + if (i > 0) { + if (coeff.compareTo(BigDecimal.ZERO) > 0) { + sb.append(" + "); + } else { + sb.append(" - "); + coeff = coeff.abs(); + } + } + + // 处理系数 + if (i == 0 || coeff.compareTo(BigDecimal.ONE) != 0) { + // 格式化系数,避免科学计数法 + String coeffStr = coeff.toPlainString(); + // 去除不必要的尾随零 + if (coeffStr.contains(".")) { + coeffStr = coeffStr.replaceAll("0+$", "").replaceAll("\\.$", ""); + } + sb.append(coeffStr); + } + + // 处理x的幂次 + if (i > 0) { + sb.append("x"); + if (i > 1) { + // 使用Unicode上标数字 + sb.append(getSuperscript(i)); + } + } + } + + return sb.toString(); + } + + /** + * 获取数字的Unicode上标表示 + */ + private static String getSuperscript(int number) { + String numStr = String.valueOf(number); + StringBuilder superscript = new StringBuilder(); + for (char c : numStr.toCharArray()) { + switch (c) { + case '0': superscript.append('⁰'); break; + case '1': superscript.append('¹'); break; + case '2': superscript.append('²'); break; + case '3': superscript.append('³'); break; + case '4': superscript.append('⁴'); break; + case '5': superscript.append('⁵'); break; + case '6': superscript.append('⁶'); break; + case '7': superscript.append('⁷'); break; + case '8': superscript.append('⁸'); break; + case '9': superscript.append('⁹'); break; + default: superscript.append(c); + } + } + return superscript.toString(); + } } \ No newline at end of file