传入金额和红包个数即可,直接上代码
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.List;
import com.google.common.collect.Lists;
public class RedBagUtils {
/**
* 每个红包最小金额,单位为分
*/
private static final int MIN_MONEY = 1;
/**
* 红包金额的离散程度,值越大红包金额越分散
*/
private static final double DISPERSE = 10;
/**
* 根据剩余的红包金额和红包个数,获取一个红包的金额
* @param amount 剩余金额,单位为元
* @param count 剩余红包数
* @return 红包金额, 单位为元
*/
public static BigDecimal getOneRedBag(BigDecimal amount, int count) {
//将 元*100 转为分
int money = amount.setScale(2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).intValue();
if (money / count < MIN_MONEY) {
throw new RuntimeException("最小值设置过大");
}
//最大值 = 均值*离散程度
int max = (int) (money * DISPERSE / count);
//最大值不能大于总金额
max = max > money ? money : max;
return new BigDecimal(randomBetweenMinAndMax(money, count, MIN_MONEY, max)).divide(new BigDecimal(100), 2,
RoundingMode.HALF_UP);
}
/**
* 在最小值和最大值之间随机产生一个红包
* @param money
* @param count
* @param min : 最小金额
* @param max : 最大金额
* @return
*/
private static int randomBetweenMinAndMax(int money, int count, int min, int max) {
//最后一个红包直接返回
if (count == 1) {
return money;
}
//最小和最大金额一样,返最小和最大值都行
if (min == max) {
return min;
}
//最小值 == 均值, 直接返回最小值
if (min == money / count) {
return min;
}
//min<=随机数bag<=max
int bag = ((int) Math.rint(Math.random() * (max - min) + min));
//剩余的均值
int avg = (money - bag) / (count - 1);
//比较验证剩余的红包还够不够分(均值>=最小值 是必须条件),不够分的话就是最大值过大
if (avg < MIN_MONEY) {
/*
* 重新随机一个红包,最大值改成本次生成的红包金额
* 由于 min<=本次红包金额bag<=max, 所以递归时bag是不断减小的。
* bag在减小到min之间一定有一个值是合适的,递归结束。
* bag减小到和min相等时,递归也会结束,所以这里不会死递归。
*/
return randomBetweenMinAndMax(money, count, min, bag);
} else {
return bag;
}
}
public static void main(String[] args) {
//红包金额
BigDecimal amount = new BigDecimal(100);
//红包个数
int count = 50;
//累计单个红包的金额,最后这个数要和amount一致才对
BigDecimal total = new BigDecimal(0);
List<BigDecimal> list = Lists.newArrayList();
for (int i = 0; i < count; i++) {
BigDecimal tem = getOneRedBag(amount.subtract(total), count - i);
total = total.add(tem);
list.add(tem);
System.out.println("第" + (count - i) + "个红包的金额是:" + total + "元");
}
//总金额是否相等
System.out.println("总计金额是否相等:" + (total.compareTo(amount) == 0));
System.out.println("红包个数:" + list.size());
System.out.println("红包金额明细:" + list);
Collections.sort(list);
System.out.println("排序后的红包明细:" + list);
}
}
分享到:
相关推荐
该资源包含微信发红包类、 二维码类 、 批量下载类、代码清晰。直接引入可用
先介绍一下项目场景,主要是通过微信小程序二维码裂变分享,每个账号有专属邀请二维码,分享出去,有新人扫码入驻,就可以得到现金奖励或红包奖励。当然,产品设计会更丰富,不止有裂变模式,还有渠道推广模式,还有...
主要为大家详细介绍了java和php版的微信随机生成红包金额算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
今天我们谈一谈JAVA中的随机数 你好WO SHI 七七卡卡 ^ _ ^ 随机数 ——Math.random() 0.0 在Math类中存在一个random()方法,用于产生随机数字,这个方法生成在0.0<=生成数<1.0 0.1那么它默认的生成的数显然在...
现在日常生活中抢红包已经成了日常游戏,本篇文章主要介绍了Java抢红包的红包生成算法,具有一定的参考价值,有需要的可以了解一下。
主要介绍了JAVA随机数随机字母的实现(微信抢红包小练习),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
最近由于公司有一个向谷歌网站上传文件的需求,需要进行web的自动化测试,选择了selenium这个自动化测试...支持自动录制动作和自动生成 .Net、Java、Python等不同语言的测试脚本。 环境搭建步骤: 1、首先要下载Pyth
(在进入微信公众号时,会为用户创建钱包,同时应用钱包向用户钱包转Gas费,留言完成,采用文本上链写入公链,同时会发红包面页面。3、进入查看余额页面项目开发使用进入 页面进行配置。新的appcode,appname会生成一...
现金红包,可添加任意金额的红包,到账方式后台可设置为到软件的用户余额里或使用微信付款到零钱接口到用户微信零钱。 5.cps,小程序跳转,如:美团红包,各平台推广优惠券,用户抽中后可以点击领取,不仅给用户...
(qq语音红包.js (协议)快阅读.js (可修改王者荣耀启动动画)视频播放器(1).js (实?).js (小瓜)九州行(720x1440)多账号游戏辅助.js -控件集合.js -控件集合2.js 0(1).js 0(2).js 0.js 00-仿真曲线滑动2.js ...