背景

由于各种原因需要后端来计算每个项所占的百分比,但是会发现计算的各项百分比合计不绝对是100,不能简单的对各项使用四舍五入法,舍九法,进一法等。

思路

使用最大余额法(比例代表制投票制度下,一种议席分配的方法,结尾有描述)

举个具体例子就很好理解:总计29个员工给3个组投票,请计算出各组所占的百分比,精确到整数。

常规计算出百分比如下:

组名 票数 计算值(%) 精确到整数 小数余额
A组 10 34.482..... 34 0.482.....
B组 12 41.379..... 41 0.379.....
C组 7 24.137..... 24 0.137.....

但是很明显,计算值存在小数,产品经理要求精确到整数,且最终的百分比合计又需要等于100,还剩下最后一个数分给谁?

按照最大余额法,应该将最后一个数分给小数余额最大的A组(0.482.....)。同理,如果多出两个数,第二多出的数应该分给小数余额第二大的组。

使用java编码实现如下

为了方便观察,封装了实体类:

@Data
@NoArgsConstructor
public class PercentVo {/*** 数量*/private int number;/*** 百分比*/private int percent;/*** 小数点后的余额,不需要返回给前端*/@JSONField(serialize = false)private Double point;/*** 组名*/private String name;public PercentVo(int number, String name) {this.number = number;this.name = name;}
}

方法及测试类:

public class NumberUtils {/*** 最大余额法,精度为整数** @param list*/public static void calculatePercent(List<PercentVo> list) {//求和:总票数int sum = list.stream().mapToInt(PercentVo::getNumber).sum();for (PercentVo percentVo : list) {double value = percentVo.getNumber() * 100 / (double) sum;int valueInt = (int) value;//设置对应的百分比percentVo.setPercent(valueInt);//获取小数点后的值percentVo.setPoint(value - valueInt);System.out.println("percentVo = " + percentVo);}//求和:当前各项百分比合计。由于我们舍弃了小数位,所以该合计只会小于等于100int curSum = list.stream().mapToInt(PercentVo::getPercent).sum();while (curSum < 100) {//找出小数余额最大的组,对其进行加1PercentVo max = list.stream().max(Comparator.comparingDouble(PercentVo::getPoint)).get();max.setPercent(max.getPercent() + 1);//当前这个数已经加1了,不应该参与下一轮的竞选max.setPoint(0.0);curSum++;}}public static void main(String[] args) {PercentVo v1 = new PercentVo(10, "A组");PercentVo v2 = new PercentVo(12, "B组");PercentVo v3 = new PercentVo(7, "C组");List<PercentVo> list = Arrays.asList(v1, v2, v3);System.out.println("处理前--------------------------");calculatePercent(list);System.out.println("处理后--------------------------");for (PercentVo percentVo : list) {System.out.println(percentVo);}}
}

结果打印如下:

处理前--------------------------
percentVo = PercentVo(number=10, percent=34, point=0.48275862068965836, name=A组)
percentVo = PercentVo(number=12, percent=41, point=0.3793103448275872, name=B组)
percentVo = PercentVo(number=7, percent=24, point=0.137931034482758, name=C组)
处理后--------------------------
PercentVo(number=10, percent=35, point=0.0, name=A组)
PercentVo(number=12, percent=41, point=0.3793103448275872, name=B组)
PercentVo(number=7, percent=24, point=0.137931034482758, name=C组)

扩展:这里为了方便,仅做了精确到整数,还可以扩展为:添加入参2,自定义精度。来提高适用性,思路是一样的。

延申

最大余额方法(英文:Largest Remainder Method)又称数额制,是比例代表制投票制度下,一种议席分配的方法,相对于最高均数方法。

透过最大余额方法,候选人须以名单参选,每份名单的人数最多可达至相关选区内的议席数目。候选人在名单内按优先次序排列。选民投票给一份名单,而不是个别候选人。投票结束后,把有效选票除以数额。一份名单每取得数额1倍的票数,便能获分配一个议席。每份名单的候选人按原先订立的顺序当选。

如此类推、将议席分配至每份名单的余额,均比数额为低的时候,则从最大余额者顺序分配余下议席;最大余额方法因而得名。

JAVA计算饼图百分比合计不是100的问题处理,最大余额法相关推荐

  1. [Java]计算从今天算起,100天以后是几月几号,并格式化成xxxx年x月x日的形式打印出来。

    Tip: 调用 Calendar 类的 add()方法计算 100 天后的日期 调用 Calendar 的 getTime() 方法返回 Date 类型对象 使用 FULL 格式的 DateForma ...

  2. JAVA计算斐波那契第100万项的最快算法排名汇总

    最近在知乎上看到一个有趣的算法题:斐波那契数列的第一百万项怎么用 C++ 求? 看了几个大神的解答后,注意到很少有用JAVA代码去解决这个问题的,可能一方面java对这种超大数高精度的运算本身就不是特 ...

  3. Echarts饼图百分比算法利用Java实现

    问题:在开发中有这样的问题,就是需要在其他地方展示百分比,但是自己计算的百分比通过四舍五入后,与饼图里面的百分比不一致的问题,要想解决这个问题,那么必须要使用echarts源码中的计算方式.当存在四舍 ...

  4. echarts饼图百分比不为100%

    一.问题 由于需要兼容低版本ie,使用的echarts版本较低,为2.2.x.当前版本有饼图百分比不为100%的问题,如数据为如下: [ { name: '测试1', value: 1 }, { na ...

  5. JAVA计算:用 100 元钱买 100 支笔,其中钢笔 3 元 / 支,圆珠笔 2 元 / 支,铅笔 0.5 元 / 支,问钢笔、圆珠笔和铅笔可以各买多少支 ?

    Java 计算 用 100 元钱买 100 支笔,其中钢笔 3 元 / 支,圆珠笔 2 元 / 支,铅笔 0.5 元 / 支,问钢笔.圆珠笔和铅笔可以各买多少支 ? 穷举法,用JAVA写了一下,代码很 ...

  6. Java计算1到100阶乘和

    Java计算1到100阶乘和 1.定义一个 factorial类 2.定义一个测试类Cs2 1.定义一个 factorial类 import java.math.BigDecimal; public ...

  7. java 画饼图和图案

    一. 饼图 import java.awt.*;import javax.swing.*;import java.awt.event.*;import java.math.*;import java. ...

  8. java如何计算时间天数差,java计算两个时间相差天数的方法汇总

    问题描述: 输入:两个日期 输出:两个日期相差的天数 具体代码实现 方法1: 通过calendar类的日期比较.注意:这里需要考虑一下: 日期是跨年份的,如一个是2012年,一个是2015年的 年份是 ...

  9. Cognos 10.1 饼图百分比小数点显示的问题

    早上用Cognos 10.1 做了一张销售百分比的饼图,发现有一个区域的销售显示0%.之后在数据中添加了计算项百分比,保留两位小数.在饼图显示值中直接使用计算的百分比,保留两位小数位,结果值竟然直接不 ...

最新文章

  1. 智源论坛(第5期)活动报名 | 机器学习系列报告会(7月4日、10日)
  2. (转载)MyEclipse github
  3. linux命令tcpdump
  4. POJ 2492 A Bug's Life 带权并查集
  5. ubuntu安装远程桌面连接工具
  6. 【漫画】最近,老王又双叒get了CDN的新技能—可编程化敏捷开发
  7. Tensorflow 学习二 tf.Session().run
  8. 哈尔滨现大雾天气 高速封闭航班推迟起飞
  9. jsp 基本语法学习笔记
  10. 选offer的5个维度
  11. 又一款性能调优神器,真香!
  12. Mybatis Sql 大于号小于号不兼容
  13. uniapp 小程序生成二维码 (兼容H5、微信小程序)
  14. Unity 5.x游戏开发指南笔记(一)
  15. Egret + P2物理引擎入门教程
  16. 页面置换算法(FIFOLRU)
  17. 《翻译与本地化CAT软件实用教程》目录
  18. ipadpro编写java代码_iPad Pro变生产力工具,你还缺个轻量级浏览器端代码编辑器...
  19. VS2005中使用Qt4.8.5遇到的问题
  20. can总线隔离中继器、canbridge-100、CanRepeater的can波特率和滤波设置

热门文章

  1. 想低成本创业,有什么推荐项目吗?
  2. 数字系统设计实验六:用verilog实现4位led译码器电路
  3. Spring Boot 3.0 新书终于出炉,荣获京东计算机图书排行榜 TOP 1!
  4. python工具 - 批量文件重命名
  5. Linux主分区和扩展分区的区别
  6. Springboot+vue 外卖订餐餐饮管理系统#毕业设计
  7. 最新cocoapods安装流程,安装过程中遇到的问题及解决方法
  8. 李开复:给创新工场求职者的一封信
  9. 【已解决】ADT中通过Android SDK Manager去安装x86的image时无法下载
  10. 阿里OSS 渗透案例