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));
    }

}
时间: 2024-10-12 16:54:11

java 红包规则的相关文章

eclipse使用与java语法规则

eclipse的使用 1.运行点击"三角图标"或右键Run As运行2.3. java语法规范 1.括号要成对出现2.每句代码应该有分号结束3.java语法区分大小写4.一个文件只能写一个带有public的class声明,还必须和文件名一致.一个文件中不可以有多个带有public的修饰符号5.名称写的时候不要包含关键字和非法字符(字母和下划线开头可以,也可以用数字结尾)6.java代码的语法全部都是半角符号7.学会规范的写代码. 写代码的好习惯: 1.常按保存,写完一句或几句就按一次C

JAVA编程规则【转自java编程思想】

本附录包含了大量有用的建议,帮助大家进行低级程序设计,并提供了代码编写的一般性指导: (1) 类名首字母应该大写.字段.方法以及对象(句柄)的首字母应小写.对于所有标识符,其中包含的所有单词都应紧靠在一起,而且大写中间单词的首字母.例如:ThisIsAClassNamethisIsMethodOrFieldName若在定义中出现了常数初始化字符,则大写static final基本类型标识符中的所有字母.这样便可标志出它们属于编译期的常数.Java包(Package)属于一种特殊情况:它们全都是小

81.JAVA编程思想——JAVA编程规则

81.JAVA编程思想--JAVA编程规则 (1) 类名首字母应该大写.字段.方法以及对象(句柄)的首字母应小写.对于所有标识符,其中包含的所有单词都应紧靠在一起,而且大写中间单词的首字母.例如: ThisIsAClassName thisIsMethodOrFieldName 若在定义中出现了常数初始化字符,则大写static final 基本类型标识符中的所有字母.这样便可标志出它们属于编译期的常数. Java 包(Package)属于一种特殊情况:它们全都是小写字母,即便中间的单词亦是如此

Java命名规则详细总结

Class名应是首字母大写的名词.命名时应该使其简洁而又具有描述性.异常类的命名,应以Exception结尾.Interface的命名规则与Class相同 1. JAVA源文件的命名 JAVA源文件名必须和源文件中所定义的类的类名相同. 2. Package的命名 Package名的第一部分应是小写ASCII字符,并且是顶级域名之一,通常是com.edu.gov.mil.net.org或由ISO标准3166.1981定义的国家唯一标志码.Package名的后续部分由各组织内部命名规则决定,内部命

《疯狂Java讲义(第3版)》.(李刚)——java命名规则及编码规范

1.命名规则: 此处借鉴一下他人的资料,比较全面一些,方便了解学习. JAVA源文件的命名 JAVA源文件名必须和源文件中所定义的类的类名相同. Package的命名 Package名的第一部分应是小写ASCII字符,并且是顶级域名之一,通常是com.edu.gov.mil.net.org或由ISO标准3166.1981定义的国家唯一标志码.Package名的后续部分由各组织内部命名规则决定,内部命名规则指定了各组件的目录名,所属部门名.项目名等. Class/Interface的命名 Clas

自己整理的一套java编码规则,让自己写代码不会那么乱

1.命名规范 (1)所有的标示符都只能用ASCⅡ字母(A-Z或a-z).数字(0-9)和下划线"_". (2)类名是一个名词,采用大小写混合的方式,每个单词的首字母大写.例如:UserInfo (3)接口的大小写规则与类名相似:例如:UserInterface. (4)方法名是一个动词或动词词组,采用大小写混合的方式,第一个单词的首字母小写,其后单词的首字母大写.例如:setName(String name). (5)变量名采取驼峰式命名,第一个字母小写,任何中间单词的首字母大写.变量

java 重载规则

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

Java命名规则

1.包的命名 Java包的名字都是由小写单词组成.但是由于Java面向对象编程的特性,每一名Java程序员都可以编写属于自己的Java包,为了保证为一个Java包命名的唯一性,在最新的java编程规范中要求在自己的包名称之前加上唯一的前缀.由于互联网的域名称都是不会重复的.所以程序员一般采用自己在互联网上的域名称作为自己程序包的唯一前缀. 例如: net.frontfree.javagroup 包划分及命名规则: com.mycompany.util com.mycompany.myprojec

Android开发中java 命名规则包的命名

ava包的名字都是由小写单词组成.但是由于Java面向对象编程的特性,每一名Java程序员都可以编写属于自己的Java包,为了保障每个Java包命名的唯一性,在最新的Java编程规范中,要求程序员在自己定义的包的名称之前加上唯一的前缀.由于互联网上的域名称是不会重复的,所以程序员一般采用自己在互联网上的域名称作为自己程序包的唯一前缀. 例如: net.frontfree.javagroup 包划分及命名规则: java代码:com.mycompany.utilcom.mycompany.mypr