package com.tievd.jyz.util; import java.util.ArrayList; import java.util.List; /** * 百分比工具类 * * @author yang'zhi'shui */ public class PercentUtil { /** * 百分之和校准等于1 * * @param arr 集合 * @param sum 总数 * @param precision 精度 * @return */ public static List getPercentValue(List arr, double sum, int precision) { Double[] seats = new Double[arr.size()]; //10的2次幂是100,用于计算精度。 double digits = Math.pow(10, precision); for (int idx = 0; idx < arr.size(); idx++) { //求和 if (sum <= 0) { for (int i = 0; i < arr.size(); i++) { sum += arr.get(i); } } //扩大比例100 double[] votesPerQuota = new double[arr.size()]; for (int i = 0; i < arr.size(); i++) { double val = arr.get(i) / sum * digits * 100; votesPerQuota[i] = val; } //总数,扩大比例意味的总数要扩大 double targetSeats = digits * 100; //再向下取值,组成数组 for (int i = 0; i < votesPerQuota.length; i++) { seats[i] = Math.floor(votesPerQuota[i]); } //再新计算合计,用于判断与总数量是否相同,相同则占比会100% double currentSum = 0; for (int i = 0; i < seats.length; i++) { currentSum += seats[i]; } //余数部分的数组:原先数组减去向下取值的数组,得到余数部分的数组 double[] remainder = new double[arr.size()]; for (int i = 0; i < seats.length; i++) { remainder[i] = votesPerQuota[i] - seats[i]; } while (currentSum < targetSeats) { double max = 0; int maxId = 0; int len = 0; for (int i = 0; i < remainder.length; ++i) { if (remainder[i] > max) { max = remainder[i]; maxId = i; } } //对最大项余额加1 ++seats[maxId]; //已经增加最大余数加1,则下次判断就可以不需要再判断这个余额数。 remainder[maxId] = 0; //总的也要加1,为了判断是否总数是否相同,跳出循环。 ++currentSum; } } List list = new ArrayList<>(); for (int i = 0; i < seats.length; i++) { list.add(i, seats[i] / digits / 100); } return list; } }