java 计算数值百分比精度,相加百分比等于100

该代码提供了一个名为PercentageCalculatorUtil的工具类,用于根据投票数计算Option对象的百分比。它使用BigDecimal进行精确计算,确保总和为NumberEnum.ONE_HUNDRED.getCode(),即100。如果总和不等于100,则会调整最小的百分比以补足差值。
摘要由CSDN通过智能技术生成

 直接附上util类

NumberEnum.ONE_HUNDRED.getCode() 为 100 也就是你要的最终和为多少
public class PercentageCalculatorUtil {

    @Data
    private static class IdDecimalTuple {
        /**
         * 传送的对象
         */
        private Option id;
        /**
         * 精度
         */
        private BigDecimal decimal;

        IdDecimalTuple(Option id, BigDecimal decimal) {
            this.id = id;
            this.decimal = decimal;
        }
    }

    @Data
    public static class Option {

        /**
         * 原数字
         */
        private Integer voteCount;

        /**
         * 占的百分比
         */
        private Integer percentage;

        /**
         * 唯一标识
         */
        private String codeStr;

        /**
         * 唯一编码
         */
        @JSONField(serializeUsing = ToStringSerializer.class)
        private Long code;

        public Option(Integer voteCount, Long code) {
            this.voteCount = voteCount;
            this.code = code;
        }

        public Option(Integer voteCount, String codeStr) {
            this.voteCount = voteCount;
            this.codeStr = codeStr;
        }
    }

    public static List<Option> computePercentage(List<Option> src) {
        Integer total = src.stream().map(Option::getVoteCount).reduce(0, Integer::sum);
        BigDecimal totalBigDecimal = BigDecimal.valueOf(total);
        BigDecimal hundredBigDecimal = BigDecimal.valueOf(NumberEnum.ONE_HUNDRED.getCode());
        List<IdDecimalTuple> decimalPartList = new LinkedList<>();
        src.forEach(votable -> {
            BigDecimal percentage = BigDecimal.valueOf(votable.getVoteCount())
                    .divide(totalBigDecimal, 6, RoundingMode.FLOOR).multiply(hundredBigDecimal);
            votable.setPercentage(percentage.setScale(0, RoundingMode.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, NumberEnum.ONE_HUNDRED.getCode())) {
            return src;
        }
        List<IdDecimalTuple> sortedEntry = decimalPartList.stream().sorted(Comparator.comparing(
                IdDecimalTuple::getDecimal).reversed()).collect(
                Collectors.toList());
        IntStream.range(0, NumberEnum.ONE_HUNDRED.getCode() - totalPercentage).mapToObj(i -> sortedEntry.get(i).getId()).forEach(option -> option.setPercentage(option.getPercentage() + 1));
        return src;

    }


    public static void main(String[] args) {
        Option a1 = new Option(1, 111L);
        Option a2 = new Option(1, 222L);
        Option a3 = new Option(1, 333L);
        Option a4 = new Option(1, 444L);
        Option a5 = new Option(12, 555L);
        Option a6 = new Option(6, 666L);
        List<Option> options = Arrays.asList(a1, a2, a3, a4, a5, a6);
        List<Option> options1 = computePercentage(options);
        System.out.println(JSON.toJSONString(options1));
    }
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C__jx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值