当你计算百分比时,每项的结果按照四舍五入来计算,会有大概率得到的所有结果相加超过 100% 或则小于 100%,比如是 99.99%,100.1% 这样的结果,可以针对此种情况进行修正,思路:找到其中最大的一项,进行修正,因为最大项修正对于结果来说不会有太大的改变,如上所示一般相差结果在 1% 以内。
下面是具体代码
/*** 结果修正* <pre>* 计算结果由于是四舍五入,可能会导致百分比相加得不到 100,或则会超过 100,需要进行修正* 修正策略:将占比最高的一项进行修正,多的减少、少的增加,各项相加最终为 100%* </pre>** @param datas ReportKVDouble 自定义业务对象,其中的 V 字段是四舍五入后的结果项,整个 list v 相加有可能超过或则低于 100%,进行修正*/private void resultCorrection(List<ReportKVDouble> datas) {ReportKVDouble max = null;Double total = 0D;for (ReportKVDouble data : datas) {if (max == null) {max = data;}if (data.getV() > max.getV()) {max = data;}total += data.getV();}// 如果该项无值,则忽略if (total == 0) {return;}if (total == 100) {return;}if (total < 100) {// 需要增加final double temp = 100D - total;// 如果值相差 1% , 则直接返回,有可能统计结果就是错误的// 四舍五入,有小数情况下,不会超过此值if (temp >= 1) {return;}double newV = add(max.getV(), temp);max.setV(newV);} else {// 需要减少final double temp = total - 100;if (temp >= 1) {return;}double newV = sub(max.getV(), temp);max.setV(newV);}}// cn.hutool.core.util.NumberUtil hutool 中的工具类/*** 相加,并保留 1 位小数** @param v1* @param v2* @return*/private double add(Double v1, Double v2) {return NumberUtil.add(new BigDecimal(v1), new BigDecimal(v2)).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();}private double sub(Double v1, Double v2) {return NumberUtil.sub(new BigDecimal(v1), new BigDecimal(v2)).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();}
