java计算百分比 加和绝对等于100%的问题

项目中遇到一个计算百分比的场景,产品要求保留整数,分项加和必须等于100,之前使用的方式是先计算出各项的百分比,再通过对期中一项的增减总数与100的差值来实现,会出现调整过大导致数据异常的情况。百度搜索并没有找到很好的答案查了google,找到了最大余额法,这里补充一个代码示例。

算法的洞见是每一个分项的误差引入都是由于精度变化引入的,所以每个分项的偏差不会大于1,上面提到的对其中一项的调整会导致多项的偏差累积到一项上,是上面方法出现数据异常的根本原因。通过对余数的排序,对多项进行处理分散了这种偏差,结果也相对合理。


public class PercentageUtil {

@Data

  private static class IdDecimalTuple{

private Optionid;

    private BigDecimaldecimal;

    IdDecimalTuple(Option id, BigDecimal decimal) {

this.id = id;

      this.decimal = decimal;

    }

}

@Data

  public static class Option{

private IntegervoteCount;

    private Integerpercentage;

  }

public static ListcomputePercentage(List src) {

Integer total = src.stream().map(Option::getVoteCount).reduce(0, Integer::sum);

    BigDecimal totalBigDecimal = BigDecimal.valueOf(total);

    BigDecimal hundredBigDecimal = BigDecimal.valueOf(100);

    List decimalPartList =new LinkedList<>();

    src.forEach(votable -> {

BigDecimal percentage = BigDecimal.valueOf(votable.getVoteCount())

.divide(totalBigDecimal,6,RoundingMode.FLOOR).multiply(hundredBigDecimal);

      votable.setPercentage(percentage.setScale(0, BigDecimal.ROUND_FLOOR).intValue());

      decimalPartList.add(new IdDecimalTuple(votable, percentage.remainder(BigDecimal.ONE)));

    });

    Integer totalPercentage = src.stream().map(Option::getPercentage).reduce(0, Integer::sum);

    if (Objects.equals(totalPercentage, 100)) {

return src;

    }

List sortedEntry = decimalPartList.stream().sorted(Comparator.comparing(

IdDecimalTuple::getDecimal).reversed()).collect(

Collectors.toList());

    for(int i=0;i<100 - totalPercentage;i++){

Option option = sortedEntry.get(i).getId();

      option.setPercentage(option.getPercentage() +1);

    }

return src;

  }

}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容