JAVA金額按比例分攤,零頭處理,java金額分攤零頭
- 金額精確計算,必須使用BigDecimal;
- 平均分攤,分攤的零頭,一般都是由資料“精度”和分攤係數決定的;
- 主要是如何對零頭進行處理,保證儘可能的平均分配。
1、按戶均攤
/** * 按戶數分攤方式 * 目的:指定金額200元,平均分配給6戶,分攤前後金額相等 */private static void hsFt() {BigDecimal[] repair_shou_Amt = new BigDecimal[6];// 每個分戶應承擔維修金額BigDecimal fact_repair_Amt = new BigDecimal("0");// 實際費用(不含零頭)//待分攤金額BigDecimal ft_amt = new BigDecimal("200");//分戶總數int count = repair_shou_Amt.length;for(int i = 0; i < count; i++) {//求每個分戶的承擔金額=分攤金額/總戶數repair_shou_Amt[i] =ft_amt.divide(new BigDecimal(count), 2, BigDecimal.ROUND_DOWN); //實際分攤承擔總金額---小數點截取後的總金額fact_repair_Amt = fact_repair_Amt.add(repair_shou_Amt[i]);}// 零頭 = 分攤實際承擔金額-待分攤金額BigDecimal repair_oddment_amt = fact_repair_Amt.subtract(ft_amt);// 算出要參與分攤零頭的戶數(精度為0.01所以*100)int repair_int = repair_oddment_amt.multiply(new BigDecimal("100")).abs().intValue();// 把維修金額零頭分攤到分戶上,如果參與維修零頭的戶數大於零或者小於總戶數,則進行分攤if( (repair_int < count) && (repair_int > 0) ) {// 如果零頭小於零,則說明有repair_int個分戶承擔的金額少一分錢0.01,需要加一分錢if( repair_oddment_amt.compareTo(new BigDecimal("0")) < 0 ) {for(int i = 0; i < repair_int; i++) {repair_shou_Amt[i] = repair_shou_Amt[i].add(new BigDecimal("0.01"));}}else {// 如果零頭大於零,則說明有repair_int個分戶承擔的金額多一分錢0.01,需要減去一分錢for(int i = 0; i < repair_int; i++) {repair_shou_Amt[i] = repair_shou_Amt[i].subtract(new BigDecimal("0.01"));}}}else if( repair_int == 0 ) {// 零頭如果為零,表示金額已全部均攤}else {throw new BusinessException("非法操作!");}}
2、按面積均攤
/** * 按面積分攤方式 * 目的:指定金額200元,平均分配給6戶,每戶面積可能不等,分攤前後金額相等 */public static void areaFt(){BigDecimal[] repair_shou_Amt = new BigDecimal[6];// 每個分戶應承擔維修金額BigDecimal fact_repair_Amt = new BigDecimal("0");// 維修對象的實際費用(不含零頭)//待分攤金額BigDecimal ft_amt = new BigDecimal("200");//分戶總數int count = repair_shou_Amt.length;//分戶面積BigDecimal[]info_area = {new BigDecimal("20.12"),new BigDecimal("10.12"),new BigDecimal("11.12"),new BigDecimal("15.12"),new BigDecimal("10.12"),new BigDecimal("110.12")};//分攤的總建面積BigDecimal totalArea = ObjectUtil.getZeroBigDecimal();for(int i = 0 ; i < count; i++){totalArea=totalArea.add(info_area[i]);}for(int i = 0; i < count; i++) {BigDecimal oa_hou_area = info_area[i];//求每個分戶的承擔金額=(分戶面積/總建築面積)*分攤金額repair_shou_Amt[i] = (oa_hou_area.multiply(ft_amt).divide(totalArea, 2, BigDecimal.ROUND_DOWN));//實際分攤承擔總金額---小數點截取後的總金額fact_repair_Amt = fact_repair_Amt.add(repair_shou_Amt[i]);}// 零頭 = 分攤實際承擔金額-待分攤金額BigDecimal repair_oddment_amt = fact_repair_Amt.subtract(ft_amt);// 算出要參與分攤零頭的戶數int repair_int = repair_oddment_amt.multiply(new BigDecimal("100")).abs().intValue();// 把維修金額零頭分攤到分戶上,如果參與維修零頭的戶數大於零或者小於總戶數,則進行分攤,否則報錯if( (repair_int < count) && (repair_int > 0) ) {// 如果零頭小於零,則說明有repair_int個分戶承擔的金額少一分錢0.01,需要加一分錢if( repair_oddment_amt.compareTo(new BigDecimal("0")) < 0 ) {for(int i = 0; i < repair_int; i++) {repair_shou_Amt[i] = repair_shou_Amt[i].add(new BigDecimal("0.01"));}}else {// 如果零頭大於零,則說明有repair_int個分戶承擔的金額多一分錢0.01,需要減去一分錢for(int i = 0; i < repair_int; i++) {repair_shou_Amt[i] = repair_shou_Amt[i].subtract(new BigDecimal("0.01"));}}}else if( repair_int == 0 ) {// 零頭如果為零,不需要處理}else {throw new BusinessException("非法操作!");}}