• JAVA实现拼手气红包算法


    实现拼手气红包算法,有以下几个需要注意的地方:

    1. 抢红包的期望收益应与先后顺序无关
    2. 保证每个用户至少能抢到一个预设的最小金额,人民币红包设置的最小金额一般是0.01元,如果需要发其他货币类型的红包,比如区块链货币或者积分,需要自定义一个最小金额。
    3. 所有抢红包的人领取的子红包的金额之和加起来,等于发红包的人发出的总红包的金额。

    下面实现的方式是一次生成所有的子红包,让用户按顺序领取。也可以每领取一个生成一个,两种方式性能上各有优劣。

    代码如下:

    /**

    * 拼手气红包算法

    * @param totalAmount 红包总金额

    * @param size 领取人数

    * @param scale 红包金额需要保留的小数位数

    * @param minAmount 单个红包的最小金额

    */

    private void randomHandOutAlgorithm(BigDecimal totalAmount, Integer size

    , Integer scale, BigDecimal minAmount) {

    //剩余红包金额

    BigDecimal remainAmount = totalAmount.setScale(scale, BigDecimal.ROUND_DOWN);

    //剩余红包个数

    Integer remainSize = size;

    for (int i = 1; i < size; i++) {

    //前n-1个红包的金额,用随机算法

    BigDecimal random = BigDecimal.valueOf(Math.random());

    BigDecimal halfRemainSize = BigDecimal.valueOf(remainSize).divide(new BigDecimal(2), BigDecimal.ROUND_UP);

    //计算单次红包的最大值,该算法也是微信的红包算法,可以保证抢红包的期望收益应与先后顺序无关,但后抢红包的方差更大,因此手气最佳更可能在后抢的人中诞生

    BigDecimal max1 = remainAmount.divide(halfRemainSize, BigDecimal.ROUND_DOWN);

    //同时,最大值需要保证,减去该红包后,剩下的红包足以满足剩余人数的最小金额

    BigDecimal minRemainAmount = minAmount.multiply(BigDecimal.valueOf(remainSize - 1)).setScale(scale, BigDecimal.ROUND_DOWN);

    BigDecimal max2 = remainAmount.subtract(minRemainAmount);

    //最终,单次红包的最大值等于两个最大值中较小的一个

    BigDecimal max = (max1.compareTo(max2) < 0) ? max1 : max2;

    BigDecimal amount = random.multiply(max).setScale(scale, BigDecimal.ROUND_DOWN);

    //每个红包的数额不能小于预设的最小金额

    if (amount.compareTo(minAmount) < 0) {

    amount = minAmount;

    }

    remainAmount = remainAmount.subtract(amount).setScale(scale, BigDecimal.ROUND_DOWN);

    remainSize = remainSize - 1;

    }

    //最后一个红包,金额等于剩余金额

    BigDecimal amount = remainAmount;

    }

    最后,未领取的金额需要退回给发红包的用户。写一个定时任务,将未领取的子红包退回即可。

    如果在用户每次领取红包的时候生成一个子红包,算法也是一样的,只是每领取一次子红包后,都要更新总红包的余额和剩余数量,然后在退回过期红包时,将总红包的余额退回给发红包的用户即可。

  • 相关阅读:
    高并发第八弹:J.U.C起航(java.util.concurrent)
    高并发第七弹:不可变对象及常用的工具类
    高并发第六弹:线程封闭(ThreadLocal)
    分布式爬取链家网二手房信息
    scrapy CrawlSpider爬取猎云网文章数据
    selenium实现12306网站自动抢票
    王者荣耀官方壁纸爬取
    使用 vsftpd 服务传输文件
    使用 Apache 服务部署静态网站
    iptables 与 firewalld 防火墙
  • 原文地址:https://www.cnblogs.com/bestJavaCoding/p/10632338.html
Copyright © 2020-2023  润新知