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. HttpUrlConnection使用Get和Post访问服务器的工具类(一)

    首先我们有一个返回响应的接口HttpCallBackListener public interface HttpCallbackListener { void onFinish(String resp ...

  2. rancher下的kubernetes之一:构建标准化vmware镜像

    学习kubernetes的时候,我们需要在kubernetes环境下实战操作,然而kubernetes环境安装并不容易,现在通过rancher可以简化安装过程,咱们来实战rancher下的kubern ...

  3. navicat如何设置外键

    今天上午刚刚弄明白了在navicat for mysql上如何设置外键,现在分享出来,希望能够对大家有帮助. 先介绍一下基本情况.现在有两个表一张是teacher表一张是dept表,现在我想把teac ...

  4. mongodb查询(转载)

    1.  基本查询:    构造查询数据.    > db.test.findOne()    {         "_id" : ObjectId("4fd58ec ...

  5. linux vi详解

    刚开始学着用linux,对vi命令不是很熟,在网上转接了一篇. vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指 ...

  6. callback回调函数-python

    链接:http://www.zhihu.com/question/19801131/answer/27459821来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 编程分 ...

  7. 【angularJS】Controller控制器

    1. 定义 控制器(Controller)在AngularJS中作用是增强视图(View),AngularJS控制器是一个构造方法,用来向视图(View)中添加额外功能. ng-controller指 ...

  8. 几张 ejabberd 架构部署图

                   

  9. filter异常捕捉

    jsp中抛出一个异常 <% String action = request.getParameter("action"); if ("accountExceptio ...

  10. IIS7、IIS7.5中应用程序池最优配置方案

    https://www.cnblogs.com/xinaixia/p/5945678.html 找到Web站点对应的应用程序池,“应用程序池” → 找到对应的“应用程序池” → 右键“高级设置...” ...