随机红包算法,每个人都有自己的实现思路。packagecom。jmmq。load。jim。importjava。math。BigDimportjava。util。Aimportjava。util。Limportjava。util。R红包算法publicclassRedPacketPrc{privatestaticfinalBigDecimalMINnewBigDecimal(0。01);publicstaticvoidmain(String〔〕args){String〔〕rsredPacketRandom(newBigDecimal(1),100,false);BigDecimalsumBigDecimal。ZERO;for(Stringstr:rs){System。out。println(str);sumsum。add(newBigDecimal(str));}System。out。println(sum:sum);System。out。println((。。。。)()(。。。。)()(。。。。)());String〔〕resredPacketOpen(newBigDecimal(20),6,false);BigDecimalsum2BigDecimal。ZERO;for(Stringstr:res){System。out。println(str);sum2sum2。add(newBigDecimal(str));}System。out。println(sum2:sum2);}paramfaceValue面值单位:元paramamount人数paramavgFlag是否平均return平均分就不写了思路一:按百分比进行随机计算,最后一个进行匝差计算publicstaticString〔〕redPacketRandom(BigDecimalfaceValue,intamount,booleanavgFlag){先计算平均数四舍五入BigDecimalperValuefaceValue。pide(newBigDecimal(amount),3,BigDecimal。ROUNDHALFUP);平均下来最小的红包必须大于等于1分钱if(perValue。compareTo(MIN)1){thrownewRuntimeException(redpacketamountOutOfBoundsmin0。01);}String〔〕rsnewString〔amount〕;平均if(avgFlag){这里四舍五入重新计算perValuefaceValue。pide(newBigDecimal(amount),2,BigDecimal。ROUNDHALFUP);Arrays。fill(rs,perValue。toString());无法除尽if(perValue。multiply(newBigDecimal(amount))。compareTo(faceValue)!0){随机获取一个下标intindexnewRandom()。nextInt(amount);rs〔index〕String。valueOf(newBigDecimal(rs〔index〕)。add(faceValue。subtract(perValue。multiply(newBigDecimal(amount)))));}}BigDecimalweightSumBigDecimal。ZERO;BigDecimalredSumBigDecimal。ZERO;BigDecimal〔〕weightsnewBigDecimal〔amount〕;随机for(inti0;irs。i){BigDecimalseednewBigDecimal(newRandom()。nextInt(amount));weightSumweightSum。add(seed);weights〔i〕循环最后一个后计算金额if(irs。length1){for(intj0;jrs。j){修改为向下取值,这样差额永远都是正数就不存在吃不掉差额的问题了BigDecimalvalfaceValue。multiply(weights〔j〕。pide(weightSum,2,BigDecimal。ROUNDHALFUP));if(val。compareTo(MIN)1){valMIN;}redSumredSum。add(val);rs〔j〕val。toString();}}}BigDecimaldifffaceValue。subtract(redSum);if(faceValue。compareTo(redSum)!0){找到第一个加上或减少diff大于MIN的元素修改金额for(inti0;irs。i){if(newBigDecimal(rs〔i〕)。add(diff)。compareTo(MIN)1){rs〔i〕newBigDecimal(rs〔i〕)。add(diff)。toString();}}}若没有任何一个元素能吃掉差额,因此差额需要进行分摊了,这里简单粗暴的将循环到大于MIN的都改为MIN同时减少差额这里代码不进行优化,会写另外一个优化的算法if(faceValue。compareTo(redSum)!0){for(inti0;irs。i){if(newBigDecimal(rs〔i〕)。compareTo(MIN)0){if(newBigDecimal(rs〔i〕)。add(diff)。compareTo(MIN)1){rs〔i〕newBigDecimal(rs〔i〕)。add(diff)。toString();}else{diff。add(newBigDecimal(rs〔i〕))。subtract(MIN);rs〔i〕MIN。toString();}}}}}上面算法进行优化paramfaceValue面值单位:元paramamount人数paramavgFlag是否平均return优化思路:上面算法为了保证红包最小金额处理上花费了大量的循环来处理优化上就直接先分配最小金额,然后在进行随机分摊剩余的钱publicstaticString〔〕redPacketOpen(BigDecimalfaceValue,intamount,booleanavgFlag){先计算平均数四舍五入BigDecimalperValuefaceValue。pide(newBigDecimal(amount),3,BigDecimal。ROUNDHALFUP);平均下来最小的红包必须大于等于1分钱if(perValue。compareTo(MIN)1){thrownewRuntimeException(redpacketamountOutOfBoundsmin0。01);}String〔〕rsnewString〔amount〕;平均if(avgFlag){这里四舍五入重新计算perValuefaceValue。pide(newBigDecimal(amount),2,BigDecimal。ROUNDHALFUP);Arrays。fill(rs,perValue。toString());无法除尽if(perValue。multiply(newBigDecimal(amount))。compareTo(faceValue)!0){随机获取一个下标intindexnewRandom()。nextInt(amount);rs〔index〕String。valueOf(newBigDecimal(rs〔index〕)。add(faceValue。subtract(perValue。multiply(newBigDecimal(amount)))));}}随机先把低保放进去Arrays。fill(rs,MIN。toString());BigDecimalweightSumBigDecimal。ZERO;BigDecimalredSumBigDecimal。ZERO;BigDecimal〔〕weightsnewBigDecimal〔amount〕;随机for(inti0;irs。i){BigDecimalseednewBigDecimal(newRandom()。nextInt(amount));weightSumweightSum。add(seed);weights〔i〕循环最后一个后计算金额if(irs。length1){for(intj0;jrs。j){BigDecimalvalfaceValue。multiply(weights〔j〕。pide(weightSum,2,BigDecimal。ROUNDDOWN));redSumredSum。add(val);rs〔j〕val。add(MIN)。toString();}}}随机获取一个下标BigDecimaldifffaceValue。subtract(redSum);intindexnewRandom()。nextInt(amount);rs〔index〕String。valueOf(newBigDecimal(rs〔index〕)。add(diff));}}