package snatchRedEnvelope;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

public class RedEnvelope {

    static Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {

        System.out.print("请输入红包金额:");
        double money = sc.nextDouble();
        System.out.print("请设置红包个数:");
        int number = sc.nextInt();

        System.out.println("\n-------------均值红包-------------");
        if (!DoubleMeanMethod(money, number)) {
            System.out.println("提示:红包参数有误!");
        }

        System.out.println("\n-------------运气红包-------------");
        if (!LineSegmentCutting(money, number)) {
            System.out.println("提示:红包参数有误!");
        }

    }

    /**
     * 拼手速红包金额算法(线段切割法)
     *
     * @param money
     * @param number
     */
    private static boolean LineSegmentCutting(double money, int number) {
        if (money <= 0 && number < 1) {
            return false;
        }
        double begin = 0; // 起始金额
        double end = money; // 最终金额
        double sum = 0; // 金额总数
        for (int i = 0; i < number - 1; i++) {
            double AmountOfTime = 0; // 次金额
            double amount = nextDouble(begin, end);
            AmountOfTime = amount - begin;
            System.out.println("提示:" + (i + 1) + "号用户领取到金额为" + format(AmountOfTime) + "元的红包!");
            sum += AmountOfTime;
            begin = amount;
        }
        sum += (end - begin);
        System.out.println("提示:" + number + "号用户领取到金额为" + format(end - begin) + "元的红包!");
        System.out.println("红包总金额验证:" + format(sum) + "元!");

        return true;
    }

    /**
     * 公平红包金额算法(二倍均值法)
     *
     * @param money
     * @param number
     * @return result
     */
    private static boolean DoubleMeanMethod(double money, int number) {
        List<Double> result = new ArrayList<Double>();
        if (money <= 0 && number < 1) { // 红包金额以及数量不符合实际情况
            return false;
        }
        double amount = 0.0; // 随机金额
        double sum = 0.0; // 金额总数
        int remainingQty = number; // 红包剩余数量
        int times = 1; // 人次计数
        while (remainingQty > 1) {
            amount = nextDouble(0.01, 2 * (money / remainingQty));
            sum += amount; // 统计金额
            System.out.println("提示:" + times + "号用户领取到金额为" + format(amount) + "元的红包!");
            money -= amount; // 总金额减去已领取金额
            remainingQty--; // 红包数量自减
            times++; // 号码自增
            result.add(amount);
        }
        sum += money;
        result.add(money);
        System.out.println("提示:" + times + "号用户领取到金额为" + format(amount) + "元的红包!");
        System.out.println("红包总金额验证:" + format(sum) + "元!");

        return true;
    }

    /**
     * 保留两位小数
     *
     * @param value
     * @return
     */
    private static String format(double value) {
        return new java.text.DecimalFormat("0.00").format(value);
    }

    /**
     * 生成(min,max)的浮点数
     *
     * @param min
     * @param max
     * @return
     */
    private static double nextDouble(double min, double max) {
        return min + ((max - min) * new Random().nextDouble());
    }

}

运行示例:

请输入红包金额:1000
请设置红包个数:10

-------------均值红包-------------
提示:1号用户领取到金额为170.42元的红包!
提示:2号用户领取到金额为173.68元的红包!
提示:3号用户领取到金额为143.08元的红包!
提示:4号用户领取到金额为0.48元的红包!
提示:5号用户领取到金额为138.01元的红包!
提示:6号用户领取到金额为112.08元的红包!
提示:7号用户领取到金额为59.60元的红包!
提示:8号用户领取到金额为112.38元的红包!
提示:9号用户领取到金额为70.01元的红包!
提示:10号用户领取到金额为70.01元的红包!
红包总金额验证:1000.00元!

-------------运气红包-------------
提示:1号用户领取到金额为99.02元的红包!
提示:2号用户领取到金额为569.40元的红包!
提示:3号用户领取到金额为67.20元的红包!
提示:4号用户领取到金额为85.79元的红包!
提示:5号用户领取到金额为124.61元的红包!
提示:6号用户领取到金额为39.08元的红包!
提示:7号用户领取到金额为11.45元的红包!
提示:8号用户领取到金额为3.29元的红包!
提示:9号用户领取到金额为0.09元的红包!
提示:10号用户领取到金额为0.05元的红包!
红包总金额验证:1000.00元!