Java随机红包算法(支持随机,定额,数量,总额)


import org.apache.commons.lang.math.RandomUtils;

import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;

public class RedPacket {
	/**
	 * 收到单个红包最大值
	 */
	private static final int MAX_AMOUNT = 20000;
	
	public static void main(String[] args) throws Exception {
		int total = 10000, //发红包的总金额
				count = 16, //红包个数
				type = 0;//发送类型
		System.out.println(String.format("红包发送总金额为:%s分,发送个数为:%s",total,count));
		int[] redPacket = generateArr(total, count, type);
		double total2 = 0;
		ArrayList<String> yuan = new ArrayList<>();
		for (int i : redPacket) {
			total2+=i;
			yuan.add(fenToYuan(String.valueOf(i)));
		}
		System.out.println("发送红包总金额:"+total2+"分,合计"+(fenToYuan(String.valueOf(total2)))+"元");


		System.out.println("红包详情:"+ yuan.toString());

	}


	/**
	 * 分转元
	 * @param amount
	 * @return
	 */
	private static String fenToYuan(String amount){
		NumberFormat format = NumberFormat.getInstance();
		try{
			Number number = format.parse(amount);
			double temp = number.doubleValue() / 100.0;
			format.setGroupingUsed(false);
			format.setMaximumFractionDigits(2);
			amount = format.format(temp);
		} catch (ParseException e){
			e.printStackTrace();
		}
		return amount;
	}


	
	/**
	 * 随机打乱数组
	 */
	public static void sort(int[] arr){
		for(int i=0;i<arr.length;i++){
			int p = RandomUtils.nextInt(i+1);
			int tmp = arr[i];
			arr[i] = arr[p];
			arr[p] = tmp;
		}
	}
	
	/**
	 * 生成红包数组
	 * @param amount   红包总金额(单位分)
	 * @param count	 发包个数
	 * @param type 发包类型(0、随机红包,1、定额红包)
	 * @return 红包数组
	 * 
	 */

	public static int[] generateArr(Integer amount,Integer count,int type) throws Exception{
		// 定义返回的数组
		int[] array = new int[count];
		
		if (count == 1) {
			return new int[]{amount};
		}
		
		switch (type) {
		case 0:
			// 默认分配1至每一位
			for (int i = 0; i < array.length; i++) {
				array[i] = 1;
			}
			int surplus_currency = amount - array.length,// 剩余金额数
				surplus_number = array.length;// 剩余需追加的数量
			
			for (int i = 0; i < array.length; i++) {
				
				// 没值可以追加了
				if (new Integer(0).equals(surplus_currency)) {
					break;
				}
				
				// (总数-(总包-i)*最小值) / (总包 - i) 随机安全值算法
				int safe_total = (int)Math.floor((amount - (count - i)) / (count - i));
				if (new Integer(0).equals(safe_total)) {// 随机值不能为0
					safe_total = 1;
				}
				// 该次随机值
				int randomint = surplus_currency >= safe_total - 1 ? safe_total : surplus_currency + 1;
				// 下次可能最大能剩余值
				int nextMax_currency = (MAX_AMOUNT - 1) * (surplus_number - 1);
				// 最小的随机数     剩余金额-剩余最大随机的总数(不含这一次)
				int minRandom = surplus_currency -  nextMax_currency;
				if (minRandom < 0) {
					minRandom = 0;
				}
				
				// 规避一些特殊情况,每个接近2000或1时会发生
				boolean must = (surplus_currency - count * MAX_AMOUNT <= 2 && surplus_currency - count * MAX_AMOUNT >= 0)
						/*|| surplus_currency < packet_number * 2*/;
				// 控制安全随机值           随机安全值不能大于最大限制,并且不能小于最小限 制
				if (safe_total < minRandom || safe_total > MAX_AMOUNT || must) {
					safe_total = MAX_AMOUNT;
					// 该次随机值
					randomint = surplus_currency >= safe_total - 1 ? safe_total : surplus_currency + 1;
					// 下次可能最大能剩余值
					nextMax_currency = (randomint - 1) * (surplus_number - 1);
					// 最小的随机数     剩余金额-剩余最大随机的总数(不含这一次)
					minRandom = surplus_currency -  nextMax_currency;
					if (minRandom < 0) {
						minRandom = 0;
					}
				}
				
				// 下一次最大的随机值
				int nextMaxRandomInt = nextMax_currency - (surplus_currency - (randomint - 1));
				Integer maxRandom = nextMaxRandomInt <= 0 ? nextMaxRandomInt + randomint: null;
				// 能随机          剩余的金额  - 最大随机数 >  最大随机数  * 剩余数量
				boolean canRandom = surplus_currency - (randomint - 1) > nextMax_currency ||
									nextMaxRandomInt > (randomint - 1) 
									|| !new Integer(0).equals(minRandom);

				int addNumber; // 追加的金额
				if (canRandom && !new Integer(randomint).equals(minRandom+1) && !(new Integer(randomint).equals(minRandom) && new Integer(safe_total).equals(minRandom)) ) {
					addNumber = myRandom(minRandom, maxRandom == null ? randomint : maxRandom- 1);
				}else {
					addNumber = randomint - 1;
				}
				array[i] += addNumber;
				surplus_currency -= addNumber;
				surplus_number--;
			}
			break;
		case 1:
			// 定额红包校验
			array = new int[count];
			for (int i = 0; i < array.length; i++) {
				array[i] = amount/count;
			}
			break;
		default:
			throw new Exception("类型错误!");
		}
		
		return array;
	}
	
	public static int myRandom(int min,int randomint) {
		if (min == 0) {

			return  RandomUtils.nextInt(randomint);
		}else {

			int nextInt = RandomUtils.nextInt(randomint - min);
			return nextInt + min;
		}
	}
	

	
	
	
}

需要 commons-lang包

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值