java 红包规则

拼手气红包:

规则:最大金额:全部金额/个数*倍数

最小金额:0.01

最后一个红包是全部金额-领取金额

随机分配

package com.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* 红包分发工具类
*
*/
public class CashRedPackUtils {
/**
* 一个红包最少拆分数量
*/
public static final int REDPACK_MIN_QUANTITY = 1;
/**
* 一个红包最多拆分数量
*/
public static final int REDPACK_MAX_QUANTITY = 100;
/**
* 小数位长度
*/
private static final int SCALE = 2;
/**
* 舍弃的小数位处理方式
*/
private static final RoundingMode ROUNDING_MODE = RoundingMode.HALF_EVEN;
/**
* 红包放大倍数
*/
private static final BigDecimal TIMES = new BigDecimal("3");
/**
* 单个红包最小金额
*/
public static final BigDecimal SINGLE_RED_MIN_MONEY = new BigDecimal("0.01");
/**
* 单个红包最大金额
*/
// private static final BigDecimal SINGLE_RED_MAX_MONEY = new BigDecimal("100");
/**
* 递归计算红包金额时连续错误最大值,超过此次数将返回最小值
*/
private static final int ERROR_MAX_NUM = 5;
/**
* 递归计算红包金额连续错误次数初始值
*/
private static final int ERROR_INIT_NUM = 1;
/**
* 计算金额时的小数位,1000代表3位小数
*/
private static final int FRACTION_LENGTH = 1000; /**
* 分发红包
* @param redMoney 红包总金额
* @param num 红包数量
* @return
*/
public static List<BigDecimal> SplitRedPackes(BigDecimal redMoney, int num) {
        List<BigDecimal> redInfoList = new ArrayList<>();
    // 红包有误
    if(num < REDPACK_MIN_QUANTITY || num > REDPACK_MAX_QUANTITY)
       return redInfoList;     //校验:金额大于0
if(redMoney.compareTo(BigDecimal.ZERO) != 1) {
return redInfoList;
} if(num <= 1) {
redInfoList.add(redMoney);
return redInfoList;
}
Random random = new Random();
for(int i = 0; i < num; i++) {
// System.out.println("\n" + (i+1) + "个红包信息:");
int surplusNum = num - i;//未分配金额红包数量
BigDecimal curRedMoney = fightLuckRedPacked(redMoney, surplusNum, random, ERROR_INIT_NUM);
redInfoList.add(curRedMoney);
redMoney = redMoney.subtract(curRedMoney);
// MandoAssert.notTrue(redMoney.compareTo(BigDecimal.ZERO) == -1, "红包金额有误");
// System.out.println("红包金额:" + curRedMoney + ",剩余:" + redMoney);
}
return redInfoList;
} /**
* 拼手气红包
* @param redMoney 红包金额
* @param num 红包数量
* @param random 随机数生成对象
* @param errorNum 错误测试
* @return 单个红包金额
*/
private static BigDecimal fightLuckRedPacked(BigDecimal redMoney, int num, Random random, int errorNum) {
if(num <= 1) {
return redMoney;
}
if(errorNum > ERROR_MAX_NUM) {
//随机金额产生错误次数超过上限,返回最小值
return SINGLE_RED_MIN_MONEY;
}
//每个红包最大金额 = 剩余总金额 / 未分配金额红包数量 * 红包放大倍数
int avgRedMaxMoney = redMoney.divide(new BigDecimal(num), ROUNDING_MODE).multiply(TIMES).intValue() * FRACTION_LENGTH;
BigDecimal curRedMoney = new BigDecimal(random.nextInt(avgRedMaxMoney) * 1.00 / FRACTION_LENGTH + "").setScale(SCALE, ROUNDING_MODE);
if(curRedMoney.compareTo(SINGLE_RED_MIN_MONEY) == -1) {
//红包最小值判断:小于最小红包金额,重新计算
return fightLuckRedPacked(redMoney, num, random, ++errorNum);
}
/*if(curRedMoney.compareTo(SINGLE_RED_MAX_MONEY) == 1) {
//红包最大值判断
return fightLuckRedPacked(curRedMoney, num, random, ++errorNum);
}*/
//最少保留红包金额
BigDecimal surplusMinRedMoney = SINGLE_RED_MIN_MONEY.multiply(new BigDecimal(num - 1));
//除当前红包剩余金额
BigDecimal surplusRedMoney = redMoney.subtract(curRedMoney);
if(surplusMinRedMoney.compareTo(surplusRedMoney) == 1) {
return fightLuckRedPacked(redMoney, num, random, ++errorNum);
}
return curRedMoney;
} public static void main(String[] args) {
System.out.println(SplitRedPackes(new BigDecimal("100"), 20));
} }

java 红包规则的更多相关文章

  1. 《Java编程思想第四版》附录 C Java 编程规则

    附录 C Java 编程规则 本附录包含了大量有用的建议,帮助大家进行低级程序设计,并提供了代码编写的一般性指导: (1) 类名首字母应该大写.字段.方法以及对象(句柄)的首字母应小写.对于所有标识符 ...

  2. Day01_05_Java第一个程序 HelloWorld - java类规则

    第一个程序Hello World *基础语法规则: 1. 第一个Java程序 HelloWorld! public class HelloWorld{ public static void main( ...

  3. java命名规则/规范

    Java命名规则: 名称只能由字母.数字.下划线.$符号组成. 不能以数字开头,不能包含空格. 名称不能使用Java中的关键字. Java命名规范: 项目名全部小写:     project 包名全部 ...

  4. java 重载规则

    首先看Java重载的规则: 1.必须具有不同的参数列表: 2.可以有不同的返回类型,只要参数列表不同就可以: 3.可以有不同的访问修饰符: 4.可以抛出不同的异常: 5.方法能够在一个类中或者在一个子 ...

  5. Java命名规则总结

    1. JAVA源文件的命名 JAVA源文件名必须和源文件中所定义的类的类名相同. 2. Package的命名 Package名的第一部分应是小写ASCII字符,并且是顶级域名之一,通常是com.edu ...

  6. java命名规则

    java变量命名是不能以#开头的.Java变量的命名规则如下:$ .字母.下划线开头都行,不能以数字开头 后面的可以是数字.字母.下划线, 其他的命名方式,都会报错,且不能运行. 以字母.下划线( _ ...

  7. [JAVA第二课] java命名规则

    Java良好的命名规则以及代码风格可以看出来一个程序员的功底,好多公司也会注重这方面,他们招聘员工在有些时候往往就是根据一个人的代码风格来招人,所以下面就就我知道的代码风格作简要的说明一下.Java命 ...

  8. Java中==规则

    普通对象== 一般说来,java中的==指的是比较两个对象的内存地址是否相同.同时,在java中,一旦使用new关键字,则说明在内存中开辟了一段空间,用于存储对象. 假设我们有一个Person类,请看 ...

  9. Java 命名规则

    http://lpacec.iteye.com/blog/25180包名:包名是全小写的名词,中间可以由点分隔开,例如:java.awt.event; 类名:首字母大写,通常由多个单词合成一个类名,要 ...

随机推荐

  1. 细说并发4:Java 阻塞队列源码分析(上)

    上篇文章 趣谈并发3:线程池的使用与执行流程 中我们了解到,线程池中需要使用阻塞队列来保存待执行的任务.这篇文章我们来详细了解下 Java 中的阻塞队列究竟是什么. 读完你将了解: 什么是阻塞队列 七 ...

  2. 全新Wijmo5中文学习指南正式上线

    Wijmo 是一款使用 TypeScript 编写的新一代 JavaScript/HTML5 控件集.它秉承触控优先的设计理念,在全球率先支持 AngularJS,并且支持React.VueJS以及T ...

  3. window.inner 兼容IE8

    window.getHeight = function() {     if (window.innerHeight != undefined) {         return window.inn ...

  4. BZOJ2131 免费的馅饼【线段树优化DP】

    Input 第一行是用空格隔开的二个正整数,分别给出了舞台的宽度W(1到10^8之间)和馅饼的个数n(1到10^5). 接下来n行,每一行给出了一块馅饼的信息.由三个正整数组成,分别表示了每个馅饼落到 ...

  5. 自动将 NuGet 包的引用方式从 packages.config 升级为 PackageReference

    在前段时间我写了一篇迁移 csproj 格式的博客 将 WPF.UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件,不过全过程是手工进行的,而且到最后处理 XAM ...

  6. IO流-文件夹的拷贝

    文件夹的拷贝操作 要求: 完成文件夹的拷贝,包括子目录的拷贝和所有文件的拷贝 分析: 首先,得在目标目录下创建一个与源文件夹名称相同的文件夹 遍历源文件夹中的所有文件对象,判断子文件是目录还是文件 如 ...

  7. java 并发时使用条件变量--Condition

    lock--unlock的方式在实际中使用较少,一般使用synchronized获取对象的内部锁替代,但是lock--unlock对了解synchronized有很大的帮助. 创建一个bank对象用于 ...

  8. phoenix elixir 框架简单试用

    备注:   官方提供的脚手架工具,我们可以直接使用,生成代码,同时需要nodejs 环境配置(比较简单,参考 相关资料即可)  1. 安装脚手架 mix archive.install https:/ ...

  9. tomcat  nginx  证书切换

    1. 导出公钥 keytool -export -alias tomcat -keystore <you jks>wsriakey.keystore -file <outputfil ...

  10. 谷歌被墙后,能够搜索的ip地址

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/langresser/article/details/32339707 http://209.116. ...