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. EasyPlayer RTSP Windows(with ActiveX/OCX插件)播放器支持H.265播放与抓图功能

    EasyPlayer作为业界一款比较优秀的RTSP播放器,一直深受用户的好评,经过了近3年的开发和迭代,从一开始的简单PC版本的RTSP播放功能,到如今支持PC(支持ocx插件).Android.iO ...

  2. Swift显示alert和promp confirmation

    Swift 显示alert func Alert(title:String, msg:String)->Void{ let alert = UIAlertController(title: ti ...

  3. JMter参数化

    参数化是干嘛的呢,咱们在调用接口的时候,有入参,那参数里面的值如果经常变化的话,就得每次去改了,很麻烦,这时候咱们就把需要经常变的值,改成可以变化的或者是咱们提前设置好的一些值,这样的话,调用的时候就 ...

  4. [Linux] ssh免密码登录

    目标:本地机器ssh登录远程目标机器时不用输入密码 (默认状态下,ssh user@192.xxx.x.xxx需要输入密码) 原理:通过公钥和私钥实现系统认证 实现:把本地机器的公钥复制到目标机器 具 ...

  5. Xcode5.1.1支持低版本和image not found和Couldn't register XXXX with the bootstrap server. Error: unknown error code.

    一:问题  targets中证书的设置 1.项目支持多设备(Xcode5.1.1支持低版本) 2.真机测试要确保Code Siging 设置没问题 支持的最低版本 二 :问题:image  not f ...

  6. MySQL的用户账户管理

    1.开启MySQL远程连接 1.sudo -i 2.cd /etc/mysql/mysql.conf.d/ 3.vim mysqld.cnf #bind-address = 127.0.0.1 把前面 ...

  7. 批量归一化batch_normalization

    为了解决在深度神经网络训练初期降低梯度消失/爆炸问题,Sergey loffe和Christian Szegedy提出了使用批量归一化的技术的方案,该技术包括在每一层激活函数之前在模型里加一个操作,简 ...

  8. Hadoop_10_11虚拟机02_虚拟机桥接方式联网【自己的亲测笔记】

    [桥接方式] 说明:自己搭建的时候用的是桥接,因为用的是2两个物理机搭建3台虚拟机所以采用桥接便于三个虚拟机在一个网段,但是不知道对后期有没有影响,目前搭建成功   (1)设置桥接方式 查看本地连接网 ...

  9. 20179223《Linux内核原理与分析》第四周学习笔记

    补交第三周作业 完成一个简单的时间片轮转多道程序内核 1.使用实验楼的虚拟机打开shell,用cd LinuxKernel/linux-3.9.4进入linux-3.9.4. 2.执行命令qemu - ...

  10. python(三):函数

    一.函数.名称空间与作用域 1.函数的构成 python有三种层次的抽象:(1)程序可分成多个模块:(2)每个模块包含多条语句:(3)每条语句对对象进行操作.函数大致处于第二层.函数有它的定义格式.参 ...