精华内容
下载资源
问答
  • 最大余额法
    2021-09-29 15:17:44

      前段时间测试提了一个bug,我打开一开,好家伙!原来是echarts饼状图数据展示百分比有一个与legend百分比的展示不一样。拿起手机一算果然,饼状图加在一起刚好100%,而legend加在一起是99.99%,0.01%的差距。查阅代码发现,之前同事做这部分legend的展示是通过数据四舍五入得到的,这就导致了0.01%的误差。自己有试验了几组数据,发现直接四舍五入跟饼状图展示的百分比确实会有很大差距,只能另找方法,试了几种都不好使,无奈去看了一下源码。找到了echarts百分比的算法。

      echarts饼状图百分比是根据最大余额法来算的,源码请移步百分比算法,自己也根据源码进行了修改封装了一个方法,返回对应title百分比在legend展示即可

    /**
     * 饼状图百分比算法--最大余额法
     * @param valueList 数值数组
     * @param idx 索引下标
     * @param precision 精确度
     */
    export const getPercentWithPrecision = (
      valueList: any[],
      idx: any,
      precision: number
    ): number => {
      if (!valueList[idx]) {
        return 0
      }
    
      const sum = valueList.reduce((acc, val) => {
        return acc + (isNaN(val) ? 0 : val)
      }, 0)
      if (sum === 0) {
        return 0
      }
    
      const digits = Math.pow(10, precision)
      const votesPerQuota = valueList.map(val => {
        return ((isNaN(val) ? 0 : val) / sum) * digits * 100
      })
      const targetSeats = digits * 100
    
      const seats = votesPerQuota.map(votes => {
        // Assign automatic seats.
        return Math.floor(votes)
      })
      let currentSum = seats.reduce((acc, val) => {
        return acc + val
      }, 0)
    
      const remainder = votesPerQuota.map((votes, idx) => {
        return votes - seats[idx]
      })
    
      // Has remainding votes.
      while (currentSum < targetSeats) {
        // Find next largest remainder.
        let max = Number.NEGATIVE_INFINITY
        let maxId = null
        for (let i = 0, len = remainder.length; i < len; ++i) {
          if (remainder[i] > max) {
            max = remainder[i]
            maxId = i
          }
        }
    
        // Add a vote to max remainder.
        ++seats[maxId]
        remainder[maxId] = 0
        ++currentSum
      }
    
      return seats[idx] / digits
    }
    
    更多相关内容
  • java初步实现最大余额法,自己使用过程中没发现问题(有没有其它bug,还有待验证)阅读之前请先查看前一篇 《百度echarts饼图百分比的计算规则---最大余额法》,保证理解了什么是最大余额方法。代码实现如下:package ...

    java初步实现最大余额法,自己使用过程中没发现问题(有没有其它bug,还有待验证)

    阅读之前请先查看前一篇 《百度echarts饼图百分比的计算规则---最大余额法》,保证理解了什么是最大余额方法。

    代码实现如下:

    package com.psmp_mobile.model.echarts;

    import java.util.*;

    /**

    * @Title: java模拟实现最大余额方法

    * @Description: ${todo}

    * @Version 1.0

    */

    public class PercentageSortUtil {

    /**

    * 对数据进行最大余额方法处理

    * (最终值保留两位小数)

    * @param list

    * @return

    */

    public static ListgetPercentageSort(List list){

    List> percentRsList =new ArrayList<>();

    Double sum =0D;

    for (int i =0; i < list.size(); i++) {

    EchartsDatagrid ed = list.get(i);

    String percent = ed.getThisPercentage().toString();

    // 小数点的位置

    int index =getIndex(percent, '.');

    if(percent.length()>5){

    Map map =new HashMap<>();

    String percentRs = percent.substring(0,index)+percent.substring(index, index+3);// 截取小数点后两位(不采用四舍五入)

    String percentRsTmp = percent.substring(index+3, percent.length());// 小数点两位以后的所有

    map.put("index", i);

    map.put("percentRs", percentRs);

    map.put("percentRsTmp", percentRsTmp);

    percentRsList.add(map);

    sum+=Double.valueOf(percentRs);

    }

    }

    // 筛选出需要+0.01的数据条数

    Double rs = (100-sum)*100;

    int rsInt = (int)Math.round(rs);

    // 对list进行排序 筛选出

    mapSort(percentRsList);

    int count =0;

    for (int i = percentRsList.size()-1; i >=0; i--) {

    // 不做处理将值对应到原来list的位置

    if( (count +1) > rsInt ){

    int index = Integer.valueOf(percentRsList.get(i).get("index").toString());

    Double percentRs = Double.valueOf(percentRsList.get(i).get("percentRs").toString());

    list.get(index).setThisPercentage(percentRs);

    }else{

    // 将原来的值 +0.01 后对应到原来list的位置

    int index = Integer.valueOf(percentRsList.get(i).get("index").toString());

    Double percentRs = Double.valueOf(percentRsList.get(i).get("percentRs").toString());

    Double val = percentRs+0.01D;

    Double str = (double)Math.round(val *100)/100;

    list.get(index).setThisPercentage(str);

    }

    count +=1;

    }

    return list;

    }

    /**

    * 计算小数点的位置

    * @param str

    * @param ch

    * @return

    */

    public static int getIndex(String str, char ch) {

    for (int i =0; i < str.length(); i++) {

    if (str.charAt(i) == ch) {

    return i;

    }

    }

    return -1;

    }

    /**

    * list> 进行排序

    * @param list

    */

    public static void mapSort(List> list){

    Collections.sort(list, new Comparator>() {

    public int compare(Map o1, Map o2) {

    String v1 = o1.get("percentRsTmp").toString();// v1是从你list里面拿出来的一个指定的值

    String v2 = o2.get("percentRsTmp").toString(); // v2是从你list里面拿出来的第二个指定的值

    // 从name1与name2取字段值然后比较,大于返回1,等于返回0,小于返回-1

    if(!v1.equals(v2)){

    return v1.compareTo(v2);

    }else{

    // 如果两个值相等的话还按原来的顺序,不做排序,返回-1处理。

    return -1;

    }

    }

    });

    }

    public static void main(String[] args) {

    // 根据实际业务构造较为真实的数据格式

    List list =new ArrayList<>();

    EchartsDatagrid ed1 =new EchartsDatagrid();

    ed1.setThisPercentage((19*100.0/117));

    EchartsDatagrid ed2 =new EchartsDatagrid();

    ed2.setThisPercentage((16*100.0/117));

    EchartsDatagrid ed3 =new EchartsDatagrid();

    ed3.setThisPercentage((16*100.0/117));

    EchartsDatagrid ed4 =new EchartsDatagrid();

    ed4.setThisPercentage((12*100.0/117));

    EchartsDatagrid ed5 =new EchartsDatagrid();

    ed5.setThisPercentage((11*100.0/117));

    EchartsDatagrid ed6 =new EchartsDatagrid();

    ed6.setThisPercentage((11*100.0/117));

    EchartsDatagrid ed7 =new EchartsDatagrid();

    ed7.setThisPercentage((10*100.0/117));

    EchartsDatagrid ed8 =new EchartsDatagrid();

    ed8.setThisPercentage((8*100.0/117));

    EchartsDatagrid ed9 =new EchartsDatagrid();

    ed9.setThisPercentage((7*100.0/117));

    EchartsDatagrid ed10 =new EchartsDatagrid();

    ed10.setThisPercentage((7*100.0/117));

    list.add(ed1);

    list.add(ed2);

    list.add(ed3);

    list.add(ed4);

    list.add(ed5);

    list.add(ed6);

    list.add(ed7);

    list.add(ed8);

    list.add(ed9);

    list.add(ed10);

    getPercentageSort(list);

    }

    }

    完结撒花,如有不明白的地方,可加QQ: 592998695

    展开全文
  • js最大余额法

    2020-07-09 14:25:29
    js最大余额法:解决百分比和不到100%的问题 //valueList要计算的数组 //idx要计算数组中值的下表 //precision百分比保留几位小数 getPercentValue: function(valueList, idx, precision) { // 判断是否为空 if (!...

    js最大余额法:解决百分比和不到100%的问题

    //valueList要计算的数组
    //idx要计算数组中值的下表
    //precision百分比保留几位小数
    getPercentValue: function(valueList, idx, precision) {
        // 判断是否为空
        if (!valueList[idx]) {
            return 0;
        }
        // 求和
        let sum = valueList.reduce(function(acc, val) {
            return acc + (isNaN(val) ? 0 : val);
        }, 0);
        if (sum === 0) {
            return 0;
        }
        // 10的2次幂是100,用于计算精度。
        let digits = Math.pow(10, precision);
        // 扩大比例100,
        let votesPerQuota = valueList.map(function(val) {
            return (isNaN(val) ? 0 : val) / sum * digits * 100;
        });
        // 总数,扩大比例意味的总数要扩大
        let targetSeats = digits * 100;
        // 再向下取值,组成数组
        let seats = votesPerQuota.map(function(votes) {
            return Math.floor(votes);
        });
        // 再新计算合计,用于判断与总数量是否相同,相同则占比会100%
        let currentSum = seats.reduce(function(acc, val) {
            return acc + val;
        }, 0);
        // 余数部分的数组:原先数组减去向下取值的数组,得到余数部分的数组
        let remainder = votesPerQuota.map(function(votes, idx) {
            return votes - seats[idx];
        });
        // 给最大最大的余额加1,凑个占比100%;
        while (currentSum < targetSeats) {
            //  找到下一个最大的余额,给其加1
            let max = Number.NEGATIVE_INFINITY;
            let maxId = null;
            for (let i = 0, len = remainder.length; i < len; ++i) {
                if (remainder[i] > max) {
                    max = remainder[i];
                    maxId = i;
                }
            }
            // 对最大项余额加1
            ++seats[maxId];
            // 已经增加最大余数加1,则下次判断就可以不需要再判断这个余额数。
            remainder[maxId] = 0;
            // 总的也要加1,为了判断是否总数是否相同,跳出循环。
            ++currentSum;
        }
        // 这时候的seats就会总数占比会100%
        return seats[idx] / digits;
    }
    
    var arr= [3,4,5]
    getPercentValue(arr,0,2);//25
    getPercentValue(arr,1,2);//33.33
    getPercentValue(arr,2,2);//41.67
    
    展开全文
  • java计算百分比的最大余额法

    千次阅读 2019-12-27 11:19:05
    1.在项目的过程中我们会经常的去计算一组数中每个数占这一组数...当然最大余额法并不一定是满足你的需求的,这个地方计算百分比的时候,最好还是跟客户进行沟通确认,确认过后才能进行这么操作。客户才是最终的上帝。

    1.在项目的过程中我们会经常的去计算一组数中每个数占这一组数的百分比,最近在项目的过程中就会遇到这个问题,一开始我们就简单粗暴的用这个数去除以这一组数的和得到一个保留几位小数的精确值,这种计算方式在大部分的时候是没有问题的,但是也会在大多数情况下产生问题。

    最刚开始算法:

    NumberFormat numberFormat = NumberFormat.getInstance(); // 设置精确到小数点后2位 numberFormat.setMaximumFractionDigits(2); String result = numberFormat.format((float) num1 / (float) num2 * 100);

    这种算法其实很多时候会出现问题,因为是根据精确值计算的,那么就会出现所有数的精确值加起来超过1  或者不足1的现象。

    如果 三个数  都是1  还有 3 ,3,5  那么和就是 99.99%   其实这种很多还有会超过100%的 

    需求:我们会在Echarts中引入大量的报表,Echarts中只需要把数据填进去就会自动的计算百分比,但是页面也需要展示百分比,以及后台还需要导出Excel。结果我刚开始的时候就用的这种算法去计算的,结果Echats和自己这种方式计算的就存在了一部分差异.最开始我也查了下百度,发现有一种算法,取这个数组中最大的值,让这个最大的值去进行加减操作使其最终的和等于100%。但是一顿操作确实也实现了  最终的结果是100%。但是发现echats官方并不是通过这个算法的.通过官方文档发现是通过最大余额法计算的。

    最大余额法的定义可以自寻百度解释。其实就是把这个数按照序数比例进行平分。然后把剩下的那些数在按照余数的最大值进行轮流均分。最大分配的是一个席位。直到把余下的序位分配完毕。

    这是我传入的七个数  12 ,11,5,5,3,3,2  通过上面的计算其实可以简单的概括就是

    把这一组数和相加得到值为:41    然后 依次除以41*10000  得到一组数。并且保留小数。

    2*10000/41=487.804847   3*10000/41 =731.7073170731 ....

    然后一次把这得到的余数  拆分:487.804847 :487 和0.804847   731.7073170731 :731和0.7073170731

    然后再把整数位相加 487+731+731...  最终结果为9995 

    然后再把这些小数放在一个数组中

    99995<10000  依次去找这个小数数组的最大值,小数数组最大值对应的整数值加1   依次循环直到最终的和为10000

    结束循环。然后再通过这个值去计算百分比。

    其实这就是最大余额法思路很简单。

    1.这组数和相加 2. 依次每一个数除以这组数和相加的结果  结果乘以10000 

    3. 拆分整数位和小数位  4.所有的整数位相加是否小于10000

    5.所有小数位最大值对应的整数位值加1  6.循环结束 计算百分比

    借助这个思路那么我们就开始写java方法就非常的简单了

    public static String getPercentValue(List<Integer> list,int index,int precision){
        if(CollectionUtils.isEmpty(list)){
            return "0";
        }
        //求和
        int listSum = 0;
        //for(int var : list){
            //listSum =add(listSum,var);
        //}
        double listSum = list.stream().mapToDouble(p -> p).sum();
        if(listSum == 0){
            return "0";
        }
        List<Double> seatsList = new ArrayList<>();//整数值
        List<Double> votesPerQuotaList = new ArrayList<>();//求小数得集合
        double currentSum =0;
        //10得二次幂是100用于计算精度
        double targetSeats = Math.pow(10,precision) *100;
        for(int val : list){
            //扩大比例100 用于计算
            //double result = divideToDouble((val * targetSeats),listSum);
            double result = val / sum * targetSeats;
            double seats = Math.floor(result);
            currentSum =add(currentSum,seats);//求总和
            seatsList.add (seats);//取整数位
            votesPerQuotaList.add(subtract(result,seats));//取小数位
        }
        //给最大得值加1 凑够占比100%
        while(currentSum < targetSeats){
            double max =0;int maxId =0;
            for(int i=0; i< votesPerQuotaList.size();i++){
                if(votesPerQuotaList.get(i) > max){
                    max = votesPerQuotaList.get(i);
                    maxId =i;
                }
            }
            //最大值加1 凑100
            seatsList.set(maxId,add(seatsList.get(maxId),1));
            votesPerQuotaList.set(maxId,0.0);//最大值小数位设为0
            currentSum = add(currentSum,1);
        }
         return calculatePercentage(seatsList.get(index), targetSeats);
    }
    public static String calculatePercentage(double num1,double num2){
        if(num1 ==0 || num2 ==0){
            return "0";
        }
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        return numberFormat.format( num1 / num2 *100)+"";
    }
    public static double divideToDouble (double num1,int num2){
        if(num1 ==0 || num2 ==0){
            return 0.0f;
        }
        BigDecimal b1 = new BigDecimal(num1);
        BigDecimal b2 = new BigDecimal(num2);
        return b1.divide(b2,8,BigDecimal.ROUND_DOWN).doubleValue();
    }
    public static double add(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }
    public static double subtract (double num1,double num2){
        BigDecimal b1 = new BigDecimal(num1);
        BigDecimal b2 = new BigDecimal(num2);
        return b1.subtract(b2).doubleValue();
    }

    当然最大余额法并不一定是满足你的需求的,这个地方计算百分比的时候,最好还是跟客户进行沟通确认,确认过后才能进行这么操作。客户才是最终的上帝。

    展开全文
  • 由于各种原因需要后端来计算每个项所占的百分比,但是会发现计算的各项百分比合计不绝对是100,不能简单的对各项使用四舍五入法,舍九法,进一法等。因此应该使用最大余额法来解决该问题。
  • 之后我查询了echarts的保留小数机制采用的是最大余额法。 一般求和算百分比,都会保留2位小数(默认四舍五入),所以很多时候相加不是100%的问题。 我们看到echarts的环形图、饼图和其他带有百分比的图表,相加之和...
  • // 给最大最大余额加1,凑个占比100%; while (currentSum ) { // 找到下一个最大余额,给其加1 let max = Number.NEGATIVE_INFINITY; let maxId = null; for (let i = 0, len = remainder.length; i ; ++i) { ...
  • * Notes: 最大余额法 * User: 曲帅 * DateTime: 2022/2/25 0025 18:12 * @param array $valueList 二维数组 [['count' => 1],['count' => 2],['count' => 3]] * @param $contKey string 要统计的字段 ...
  • = votesPerQuota[i] - seats[i] } while (currentSum ) { var max = 0.0 var maxId = 0 for (i in remainder.indices) { if (remainder[i] > max) { max = remainder[i] maxId = i } } //对最大余额加1 ++seats...
  • 在做某些计算的时候,需要百分比之和是100%,但是一般求和算百分比,都会保留2位小数...就是用到了最大余额法,解决了百分比总和不是100%的问题。 最大余额法计算方法: <script> /*** 使用方法****/ let a
  • 没办法只要去找方法,原本之前的项目是把剩余部分加到最大占比的地方,这次项目比较赶没做这方面的考虑,刚好饼图用Echarts发现他们相加刚好为100%,经过度娘,发现他们用的是最大余额法,就有了下面的方法,方法...
  • 最大余额法 参考文章最大余额法 php实现 //最大余额法 public function MaxBalance() { $data = [2,3,4]; $sum = array_sum($data); $res = []; foreach ($data as $key=>$item) { ...
  • 环形图将总数放置在饼图中央,且鼠标悬浮图例可以显示提示信息,图例提示信息数据计算比例采用最大余额法计算 initEchartPie() initEchartPie(){ setTimeout(()=>{ const myCharts = this.$echarts.init(this...
  • java最大余数(百分比算法Echarts)

    千次阅读 2019-11-07 13:50:06
    //对最大余额加1 ++ seats [ maxId ] ; //已经增加最大余数加1,则下次判断就可以不需要再判断这个余额数。 remainder [ maxId ] = 0 ; //总的也要加1,为了判断是否总数是否相同,跳出循环。 ++ ...
  • 基于AHP和BP神经网络的商业银行客户信用评估模型.doc
  • 1104系统针对银行业金融机构设计,用于统计辖区内机构存续业务的不良资产情况。
  • 版本 0.9债务滚雪球此小页面将计算并显示偿还... 债务雪球先支付最低​​余额。 这种方法给付款人最大的动力。 当每笔贷款还清时,旧的付款将转移到下一笔贷款。 最低还款额这是最糟糕的还款方式,让您与复利作斗争。
  • 按中奖概率最大成都消耗余额
  • 记录一次线上商户余额变动异常紧急问题排查全过程问题描述一、服务器日志排查二、mysql日志排查 问题描述 今天中午14:30,解决了一个比较紧急的余额变动问题,做软件的各位同仁应该都清除,涉及到钱的问题,往往...
  • --新增余额处理。 框架为:springboot2.x,环境搭建、maven配置略。 一个简单的前端页面模拟并发量: 两个功能:一个发红包和一个抢红包 ; charset=UTF-8" pageEncoding="UTF-8"%> Title 抢红包 启动 |抢红包人数:...
  • 生存分析研究住房抵押贷款违约风险影响因素,陈勇,海霞,住房抵押贷款违约风险研究对我国商业银行风险管理具有重要意义,为研究住房抵押贷款违约风险的影响因素,本文构建了Cox模型,用生
  • 1.1 等价类划分 1.2 边界值分析 1.3 场景 1.4 错误推测(反推) 2 等价类划分 2.1 等价类划分的概念 等价类划分是一种典型的、重要的黑盒测试方法,是指某个输入域的子集合。在该子集合中,...
  • 测试用例的定义:是为某个业务目标,而编制的一组由测试输入,执行条件以及预期结果组成的案例 ...场景: 场景见最后 证交表: 在一个界面中有多个控件,每个控件有多个取值,控件之间可以相互组合 .
  • 对于此事件流,银行系统处于联机状态,而且对授权请求给予答复,批准完成提款过程,并且据此更新帐户余额。 出钞 - 提供现金。 返回银行卡 - 银行卡被返还。 收据 - 打印收据并提供给客户。ATM 还相应地更新内部记录...
  • 【判断题】最优子结构性质的含义是问题的最优解不一定包含其子问题的最优解【多选题】企业吸收投资者出资时,下列账户余额不会发生变化的有()【单选题】4月30日,甲公司股本5000万(每股面值1元),资本公积(股份溢价)400...
  • 严蔚敏版数据结构课后习题重点算法整理

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,425
精华内容 2,570
关键字:

最大余额法