关于统计图表中的百分比之和不等于100的问题

一、问题描述

                最近用java Bigdecimal 四舍五入方式做了几个百分比统计图表,可是最后的几个汇总的和总是100.1,或者99.97。百度,google了好久。下面三种方案,第2)3)中还是会有处理不掉的情况,比如 1,1,1和是3。每个1/3 约等于33.33,没办法,我的选择是这种不做处理。三个都是1,凭啥其中一个就是33.34!

二、解决方案:

                 1)如果统计中有其他或者不重要的统计项的,这个不计算,等别的计算完了,再用100减去其他的和。

                    (听着挺合理 的,大家可以试试,我这个没有其他,所以这个不行)

                  2)google找到的一个帖子http://dovov.com/100-9.html 通过将小数部分递减的顺序加1来分配差异

关于统计图表中的百分比之和不等于100的问题

   3)这个我自创的,每次向前进一位,还是四舍五入,一直进到个位,如何还是不等于100,就不做处理。基本90%的情况都可以和变成100%。

三、相关代码

  第 2)种的实现代码

  public static void main(String[] args) {

      getResultWithGoogleSuggestion();
   }
   private static void getResultWithGoogleSuggestion() {
    List<Double> result = new ArrayList<Double>();
    // 13.626332% 47.989636% 9.596008% 28.788024
    result.add(13.62);
    result.add(47.98);
    result.add(9.59);
    result.add(28.78);
    result.add(0d);
    Collections.sort(result, new Comparator<Double>() {//按小数点的指定位数排序
        @Override
        public int compare(Double o1, Double o2) {
            return (getValue(String.valueOf(o2), 2))-(getValue(String.valueOf(o1), 2));
        }
    });
    double sum = 0;
    for (int i = 0; i < result.size(); i++) {
        sum = BigDecimalUtils.add(sum, result.get(i));
    }
    double d=BigDecimalUtils.sub(sum,100);
    double b=turnLastToOne(d);
    int w=getTimes(d);
    boolean doOrNot=true;
    if(d>0){//和100比较大
        Collections.reverse(result);
        if(getEquelsNum(result)>w){
            doOrNot=false;
        }
        if(doOrNot) {
            for (int i = 0; i < w; i++) {
                result.set(i, BigDecimalUtils.sub(result.get(i), b));
            }
        }

    }else if(d<0){//和比100小,要在指定几个上加上
        if(getEquelsNum(result)>w){
            doOrNot=false;
        }
        if(doOrNot) {
            for (int i = 0; i < w; i++) {
                result.set(i, BigDecimalUtils.sub(result.get(i), b));
            }
        }
    }
    System.out.println(result);
}

private static int getEquelsNum(List<Double> result) {
    int k=1;
    double dd=-1d;
    for(double d:result){
        if(dd!=-1){
            if(dd==d){
                k++;
            }
        }else{
            dd=d;
        }
    }
    return k;
}
private static int getTimes(double d) {
    String s=String.valueOf(d);
    return Integer.parseInt(s.substring(
    s.length()-1,s.length()));
}
private static double turnLastToOne(double d) {//获得指定位置上的数字
    String s=String.valueOf(d);
    s=s.substring(0,s.length()-1);
    return Double.parseDouble(s+"1");
}
private static int getValue(String s, int position) {//获得指定位置上的数字
    try {
        return Integer.parseInt(s.substring(s.indexOf(".") + position, s.indexOf(".") + position + 1));
    }catch (StringIndexOutOfBoundsException e){
        return -1;
    }
}


 第 3)种的实现代码

  主方法:

/* 处理百分数之和大于100的问题 start*/
 decimalPointGoUpOne(result,CommonConstants.ONE);//进一位看看
 decimalPointGoUpOne(result,CommonConstants.ZERO);//如果不对,再进一位
/* 处理百分数之和大于100的问题 end*/
double sumResult=CommonConstants.DOUBLE_ZERO;
for(int i=0;i<result.size();i++){
    sumResult= BigDecimalUtils.add(sumResult,result.get(i));
}
if (sumResult!=CommonConstants.ONE_HUNDRED){//进了2次都不能搞定,说明无限循环情况
    result= result2;//返回原来的值
}
子方法:
private void decimalPointGoUpOne(List<Double> result,int scale) {
    double sumResult=CommonConstants.DOUBLE_ZERO;
    for(int i=0;i<result.size();i++){
        sumResult= BigDecimalUtils.add(sumResult,result.get(i));
    }
    if (sumResult!=CommonConstants.ONE_HUNDRED){ //通过将小数部分递减的顺序加1来分配差异 好厉害啊
        for(int i=0;i<result.size();i++) {
            result.set(i,BigDecimalUtils.round(result.get(i),scale));
        }
    }
}

鄙人才疏学浅,代码仅供参考。有什么问题,还请各位大神不吝赐教。