当你计算百分比时,每项的结果按照四舍五入来计算,会有大概率得到的所有结果相加超过 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();
}