文档章节

红包金额均分实现

鹏城二少
 鹏城二少
发布于 2017/03/31 14:39
字数 651
阅读 29
收藏 0
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
 * 红包均分
 * 
 * @author liyulin
 * @version 1.0 2017年3月31日 上午11:28:35
 */
public final class MoneyUtil {

	/**
	 * 红包金额根据所占总金额比例均分
	 * 
	 * @param totalAmt 总金额(单位:分),为null时,会在内部计算其值
	 * @param subAmts 所有资金额(单位:分)
	 * @param totalHbAmt 红包总金额(单位:分)
	 * @return 返回所有均分的金额(单位:分)
	 */
	public static final List<BigDecimal> getSubMoney(BigDecimal totalAmt,
			List<BigDecimal> subAmts, BigDecimal totalHbAmt) {
		if (totalAmt == null) {
			totalAmt = BigDecimal.ZERO;
			for (BigDecimal subAmt : subAmts) {
				totalAmt = totalAmt.add(subAmt);
			}
		}

		/** 因为计算时,最后一个的值为总红包金额减去其余红包总额,如果最后的账单金额为0,会出现红包金额为负数的情况 */
		int dealSize = getDealSubAmtMaxIndex(subAmts);// 从最后一个开始倒序,实付为大于0的索引

		/** 最后实付金额(连续)为非0的处理 */
		List<BigDecimal> subHbAmts = dealNonNegative(dealSize, totalAmt, subAmts, totalHbAmt);
		
		/** 最后实付金额(连续)为0的处理 */
		for (int i = dealSize + 1; i < subAmts.size(); i++) {
			subHbAmts.add(BigDecimal.ZERO);
		}

		/** 分配的最后一个红包为负数的处理 */
		dealLastNegative(dealSize, subHbAmts, subAmts);

		return subHbAmts;
	}
	
	/**
	 * 非0实付处理
	 * @param dealSize
	 * @param totalAmt
	 * @param subAmts
	 * @param totalHbAmt
	 * @return
	 */
	public static final List<BigDecimal> dealNonNegative(int dealSize,
			BigDecimal totalAmt, List<BigDecimal> subAmts, BigDecimal totalHbAmt) {
		List<BigDecimal> subHbAmts = new ArrayList<BigDecimal>();
		BigDecimal otherTotalAmt = BigDecimal.ZERO;
		for (int i = 0; i <= dealSize; i++) {
			BigDecimal subHbAmt = null;
			if (i < dealSize) {
				BigDecimal subAmt = subAmts.get(i);

				subHbAmt = div(subAmt.multiply(totalHbAmt), totalAmt);
				BigDecimal subUpHbAmt = subHbAmt.setScale(0, RoundingMode.UP);
				if (subUpHbAmt.compareTo(subAmt) < 0) {
					subHbAmt = subUpHbAmt;
				} else {
					subHbAmt = subAmt;
				}

				otherTotalAmt = otherTotalAmt.add(subHbAmt);
			} else {// 最后一个
				subHbAmt = totalHbAmt.subtract(otherTotalAmt);
			}

			subHbAmts.add(subHbAmt);
		}

		return subHbAmts;
	}
	
	/**
	 * 获取处理的最后一个子帐单的索引
	 * @param subAmts
	 * @return
	 */
	public static final int getDealSubAmtMaxIndex(List<BigDecimal> subAmts){
		int dealSize = 0;// 从最后一个开始倒叙,实付为大于0的索引
		/** 因为计算时,最后一个的值为总红包金额减去其余红包总额,如果最后的账单金额为0,会出现红包金额为负数的情况 */
		for (int i = subAmts.size() - 1; i >= 0; i--) {
			BigDecimal subAmtTmp = subAmts.get(i);
			if (subAmtTmp.compareTo(BigDecimal.ZERO) != 0) {
				dealSize = i;
				break;
			}
		}
		return dealSize;
	}
	
	/**
	 * 分配的最后一个红包为负数的处理
	 * @param dealSize
	 * @param subHbAmts
	 * @param subAmts
	 */
	public static final void dealLastNegative(int dealSize, List<BigDecimal> subHbAmts, List<BigDecimal> subAmts){
		if(subHbAmts.get(dealSize).compareTo(BigDecimal.ZERO) < 0){
			long balanceAmt = Math.abs(subHbAmts.get(dealSize).longValue());
			subHbAmts.set(dealSize, BigDecimal.ZERO);
			for (int i = 0; i < dealSize; i++) {
				long partBalanceAmt = subAmts.get(i).longValue() - subHbAmts.get(i).longValue();
				if (partBalanceAmt > 0) {
					if (partBalanceAmt >= balanceAmt) {
						subHbAmts.set(i, subHbAmts.get(i).subtract(BigDecimal.valueOf(balanceAmt)));
						break;
					} else {
						subHbAmts.set(i, subHbAmts.get(i).subtract(BigDecimal.valueOf(partBalanceAmt)));
						balanceAmt -= partBalanceAmt;
						if (balanceAmt == 0) {
							break;
						}
					}
				}
			}
		}
	}
	
	public static final BigDecimal div(BigDecimal num1, BigDecimal num2) {
		if (num1 == null || num2 == null) {
			return null;
		}
		return num1.divide(num2, 4, RoundingMode.DOWN);
	}

	public static void main(String[] args) {
		List<BigDecimal> subAmts = new ArrayList<BigDecimal>();

		subAmts.add(BigDecimal.valueOf(48));
		subAmts.add(BigDecimal.valueOf(122));
		subAmts.add(BigDecimal.valueOf(196));
		subAmts.add(BigDecimal.valueOf(10));

		BigDecimal totalHbAmt = BigDecimal.valueOf(8);

		List<BigDecimal> allSubHbAmts = getSubMoney(null, subAmts, totalHbAmt);
		System.err.println(allSubHbAmts);
	}
}

 

© 著作权归作者所有

鹏城二少
粉丝 0
博文 7
码字总数 4921
作品 0
深圳
程序员
私信 提问
千米红包模式APP系统专业定制开发

  千千米红包模式APP系统专业定制开发《苏134-1619-5045》千米红包APP系统开发,千米红包模式开发系统,千米红包系统开发,千米红包模式APP系统开发,千米红包APP软件开发。   移动互联网...

系统平台APP开发
2018/03/21
0
0
微信公众平台开发(111) 现金红包、裂变红包、企业付款

在这篇微信公众平台开发教程中,我们将介绍如何在实现现金红包、裂变红包、企业付款以及红包交易查询(含现金红包和裂变红包)和企业付款查询的功能。 本文分为以下二个部分: 微信支付接口S...

bengozhong
2016/03/19
337
0
微信红包的随机算法是怎样实现的?

摘自知乎 ,答案来自:https://www.zhihu.com/question/22625187/answer/85530416 答案来自:https://www.zhihu.com/question/22625187/answer/85530416 有人问过微信的人,大致是这样: 先上...

北极之北
2016/02/23
2.4K
3
自定义微信红包金额的插件

自定义微信红包金额的,例如我发一个五毛钱的红包,我分成五份,我事先在外挂软件里设定好五份的金额分别是0.1 0.15 0.08 0.12 0.05,然后我再发红包让别人领取,不论是谁领取,也不论别人是...

坏坏小人物
2016/07/03
38
1
一款发红包程序的设计(PHP篇)

每年都要给小孩送红包,钱数10元不等。 程序设计如下: 设定总金额为10元,有N个人随机领取: N=1 第一个 则红包金额=X元; N=2 第二个 为保证第二个红包可以正常发出,第一个红包金额=0.01...

crossmix
2015/11/12
113
0

没有更多内容

加载失败,请刷新页面

加载更多

JMM内存模型(一)&volatile关键字的可见性

在说这个之前,我想先说一下计算机的内存模型: CPU在执行的时候,肯定要有数据,而数据在内存中放着呢,这里的内存就是计算机的物理内存,刚开始还好,但是随着技术的发展,CPU处理的速度越...

走向人生巅峰的大路
13分钟前
24
0
你对AJAX认知有多少(2)?

接着昨日内容,我们几天继续探讨ajax的相关知识点 提到ajax下面几个问题又是必须要了解的啦~~~ 8、在浏览器端如何得到服务器端响应的XML数据。 通过XMLHttpRequest对象的responseXMl属性 9、 ...

理性思考
22分钟前
4
0
正则表达式基础(一)

1.转义 转义的作用: 当某个字符在表达式中具有特殊含义,例如字符串引号中出现了引号,为了可以使用这些字符本身,而不是使用其在表达式中的特殊含义,则需要通过转义符“\”来构建该字符转...

清自以敬
25分钟前
4
0
idea中@Data标签getset不起作用

背景:换电脑以后在idea中有@data注解都不生效 解决办法:idea装个插件 https://blog.csdn.net/seapeak007/article/details/72911529...

栾小糖
30分钟前
4
0
Apache Kudu 不能删除不存在的数据

使用Apache Kudu客户端,对KafkaConnect Sink 进行扩展。 使用的Apache Kudu 的Java 客户端。突然有天发现作业无法提交,一直报错。 后来才发现这是Kudu自身的一种校验机制。为了忽略这种校验...

吐槽的达达仔
41分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部