一、问题描述:
最近用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来分配差异
3)这个我自创的,每次向前进一位,还是四舍五入,一直进到个位,如何还是不等于100,就不做处理。基本90%的情况都可以和变成100%。
三、相关代码
第 2)种的实现代码
public static void main(String[] args) {
getResultWithGoogleSuggestion(); } private static void getResultWithGoogleSuggestion() { List result = new ArrayList(); // 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() {//按小数点的指定位数排序 @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(dw){ 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 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