使用java进行红包分配算法

公司有个红包分发业务模块,需要红包随机生成金额,克提供参数为:
1、红包金额(最小精确到厘:0.001,数据库是用int表示,1元也就是1000厘)
2、红包发放数量
3、红包金额上限
4、红包金额下限
5、金额精度(精度可以理解为随机数能精确到小数哪一位,如范围为:0.01~0.5,如果精确到分的随机数为0.34 or 0.340,如果精确到厘:0.345)

1,2,3,4,5都可以由用户输入或选择,程序可进行判断是否参数不符计算,意思就是:
如果金额为10元,数量为10个,上限就不能大于10-0.001*9=9.991之类的
而且,金额是随用户输入,没有限制10的倍数或者100的倍数,可能会是2546
数量也是由用户输入,也可能为3254等不规则数字
需要程序使用用户金额生成在上限下限范围内随机缺固定的数量的红包个数,我想了好久了
由于数学比较差,而且红包金额可以根据精度调控后面小数位数

3个回答

我写了一个,但是感觉没那么满意

 public class Red {
    private int remain;//金额,单位厘
    private int count;//个数
    private Precision precision;//精度
    private int max;//上限,单位厘 
    private int min;//下限,单位厘
    private int[] redPool;
    private int index;

    public static void main(String[] args) {
        int count = 100;
        Red red = Red.newInstance(10 * 1000, count, Precision.FEN, 1 * 1000, 5 * Precision.FEN.getPre());
        int sum = 0;
        for (int i = 0; i < count; i++) {
            int money = red.getRed();
            sum += money;
            System.out.println(money);
        }
        System.out.println("---------------" + sum);
    }

    public int getRed() {
        return index < count ? redPool[index++] : 0;
    }

    public static Red newInstance(int money, int count, Precision precision, int max, int min) {
        Red red = new Red(money, count, precision, max, min);
        String msg;
        if ("".equals(msg = red.validate())) return red;
        else throw new RuntimeException(msg);
    }

    private Red(int money, int count, Precision precision, int max, int min) {
        this.remain = money;
        this.count = count;
        this.precision = precision;
        this.max = max;
        this.min = min;
        init();
    }

    private void init() {
        redPool = new int[count];
        int remain_ = remain;
        for (int i = 0; i < count - 1; i++) {
            int max = getRealMax(remain_, count - i);
            int min = getRealMin(remain_, count - i);
            int money = ((int)(Math.random() * (max - min + precision.getPre())) + min) 
                    / precision.getPre() * precision.getPre();//[min, realMax]
            remain_ -= money;
            redPool[i] = money;
        }
        redPool[count - 1] = remain_;
        randomPool();
    }

    private void randomPool() {
        for (int i = 0; i < count; i++) {
            int index = (int) (Math.random() * count);
            int temp = redPool[i];
            redPool[i] = redPool[index];
            redPool[index] = temp;
        }
    }

    private int getRealMax(int remain, int count) {
        int calMax = remain - ((count - 1) * min);
        return Math.min(calMax, max);
    }

    private int getRealMin(int remain, int count) {
        int calMin = remain - ((count - 1) * max);
        return Math.max(calMin, min);
    }

    public int getRemain() {
        return remain;
    }

    public void setRemain(int remain) {
        this.remain = remain;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public int getMax() {
        return max;
    }

    public void setMax(int max) {
        this.max = max;
    }

    public int getMin() {
        return min;
    }

    public void setMin(int min) {
        this.min = min;
    }

    public Precision getPrecision() {
        return precision;
    }

    public void setPrecision(Precision precision) {
        this.precision = precision;
    }

    private String validate() {
        String msg = "";
        if (remain <= 0) {
            msg = "余额不能为0";
        } else if (remain % precision.getPre() != 0) {
            msg = "余额的精度不对";
        } else if (count <= 0) {
            msg = "红包个数必须为正数";
        } else if (max % precision.getPre() != 0) {
            msg = "上限的精度不对";
        } else if (max <= min) {
            msg = "上限必须大于下限";
        } else if (min % precision.getPre() != 0) {
            msg = "下限的精度不对";
        } else if (min <= 0) {
            msg = "下限必须大于0";
        } else if (getRealMax(remain, count) < getRealMin(remain, count)) {
            msg = "上下限设置错误";
        }
        return msg;
    }

}
enum Precision {
    LI(1),
    FEN(10),
    JIAO(100),
    YUAN(1000);

    private int pre;
    private Precision(int pre) {
        this.pre = pre;
    }
    public int getPre() {
        return pre;
    }
}
u011428089
剑城渔翁 我也写了好多种方案,也请教了各路朋友,最终,都没有一个能准确的比较人性化的算法,如果要有人性化,必须要用性能来换,要用很多判断,就更复杂了,这对于上万个红包分发来说,有点吃力,最终我弄出来的跟你这个差不多
接近 2 年之前 回复

简单的实现就是逻辑采用随机数的方式
比如 10元发10个数量,按照你说的10*1000 = 10000厘
1.生成个9999以内的随机数 比如说生成5300 计数1
2.10000-5300 = 4700 再次生成一个4700内的随机数 计数+1
3.依次类推 最后到9次的时候 使用10000-生成所有随机数之和这样就生成最后一个金额

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐