微信红包算法研究
2017-02-20 23:17
183 查看
package com.galaxy.fym.algorithm.maxsublist; import java.math.BigDecimal; import java.util.*; /** * Created by fengyiming on 2017/2/17. * * @author fengyiming * 随机产生红包:金额正太分布 * * 如果非标准正态分布X~N(μ,σ^2),那么关于X的一个一次函数 (X-μ)/σ ,就一定是服从标准正态分布N(0,1)。 * 举个具体的例子,一个量X,是非标准正态分布,期望是10,方差是5^2(即X~N(10,5^2));那么对于X的线性函数Y=(X-10)/5,Y就是服从标准正态分布的Y~N(0,1)。 */ public class RedPacket { private static Random random = new Random(); private static BigDecimal MIN_VALUE = new BigDecimal("0.01"); private static boolean isMin = false; /** * 生成红包 * * @param amountValue 红包总金额 * @param sizeValue 红包大小 * @param maxMutValue 剩余红包限定倍数 * @param sigmaValue 标准差倍数 * @return */ public static List<BigDecimal> getAllHotPacket(double amountValue, double sizeValue, double maxMutValue, double sigmaValue) { //红包总金额 BigDecimal amount = new BigDecimal(String.valueOf(amountValue)); BigDecimal restAmount = amount; BigDecimal size = new BigDecimal(String.valueOf(sizeValue)); BigDecimal mu = restAmount.divide(size, 2, BigDecimal.ROUND_HALF_DOWN); BigDecimal avg = new BigDecimal(mu.toString()); BigDecimal MAX_MUT = new BigDecimal(String.valueOf(maxMutValue)); double sigma = sigmaValue <= 0 ? 1 : sigmaValue; List<BigDecimal> hotPacketPool; do { hotPacketPool = new ArrayList<BigDecimal>(size.intValue()); int hotPacketSize = size.intValue() - 1; //随机出前size-1个红包,最后一个红包取剩余值,并且最后一个红包不能过大,有均值的限定倍数 for (int i = 0; i < hotPacketSize; i++) { BigDecimal randomBigDecimal = getRandomHotPacketAmount(mu.doubleValue(), sigma, restAmount, size.intValue()-1); restAmount = restAmount.subtract(randomBigDecimal); //System.out.println("剩下的红包金额:" + restAmount); size = size.subtract(BigDecimal.ONE); mu = restAmount.divide(size, 2, BigDecimal.ROUND_HALF_DOWN); hotPacketPool.add(randomBigDecimal); } hotPacketPool.add(restAmount); } while (restAmount.compareTo(avg.multiply(MAX_MUT)) > 0); //打乱红包顺序,因为越早的红包均值最高 //倒序遍历list,然后在当前位置随机一个比当前位置小的int数字,交换数字 Collections.shuffle(hotPacketPool); return hotPacketPool; } /** * 根据剩余红包金额均值,标准差大小,计算出随机红包的大小 * * @param mu * @param sigma * @param rest 剩下的钱 * @param restSize 还剩多少红包 * @return */ private static BigDecimal getRandomHotPacketAmount(double mu, double sigma, BigDecimal rest, int restSize) { if(isMin){ return MIN_VALUE; } BigDecimal radomNo; //剩余最小的钱 BigDecimal minRest = MIN_VALUE.multiply(new BigDecimal(restSize)); //随机出的红包也得满足剩余红包最少0.01 do { radomNo = getRandom(mu, mu * sigma); } while (rest.subtract(radomNo).subtract(minRest).compareTo(BigDecimal.ZERO) < 0); if(rest.subtract(radomNo).subtract(minRest).compareTo(BigDecimal.ZERO) == 0){ isMin = true; } BigDecimal randomBigDecimal = radomNo; //对红包金额取2位小数 randomBigDecimal = randomBigDecimal.setScale(2, BigDecimal.ROUND_HALF_DOWN); //判断金额不能小于0.01元 randomBigDecimal = randomBigDecimal.compareTo(MIN_VALUE) > 0 ? randomBigDecimal : MIN_VALUE; return randomBigDecimal; } /** * 产生mu sigma的正态分布的double值 * * @param mu * @param sigma * @return */ private static BigDecimal getRandom(double mu, double sigma) { double randomValue = random.nextGaussian() * sigma + mu; BigDecimal value = new BigDecimal(String.valueOf(randomValue)).abs(); return value; } public static void main(String[] args) { BigDecimal all = BigDecimal.ZERO; List<BigDecimal> allHotPacket = getAllHotPacket(10d, 10d, 3d, 1d); int size = allHotPacket.size(); BigDecimal max = BigDecimal.ZERO; int maxIndex = 0; for (int i = 0; i < size; i++) { BigDecimal amout = allHotPacket.get(i); System.out.println("第" + (i + 1) + "随机的红包金额大小:" + amout); if (amout.compareTo(max) > 0) { max = amout; maxIndex = i + 1; } all = all.add(amout); } System.out.println("所有红包金额为红包:" + all); System.out.println("手气最佳为:第" + maxIndex + "个红包,金额为:" + max); } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
[/code]
第1随机的红包金额大小:0.15 第2随机的红包金额大小:1.48 第3随机的红包金额大小:0.02 第4随机的红包金额大小:2.21 第5随机的红包金额大小:1.14 所有红包金额为红包:5.00 手气最佳为:第4个红包,金额为:2.21 第1随机的红包金额大小:0.13 第2随机的红包金额大小:0.65 第3随机的红包金额大小:2.30 第4随机的红包金额大小:0.95 第5随机的红包金额大小:0.97 所有红包金额为红包:5.00 手气最佳为:第3个红包,金额为:2.30 第1随机的红包金额大小:4.74 第2随机的红包金额大小:0.88 第3随机的红包金额大小:1.07 第4随机的红包金额大小:0.20 第5随机的红包金额大小:0.43 第6随机的红包金额大小:0.41 第7随机的红包金额大小:0.22 第8随机的红包金额大小:0.20 第9随机的红包金额大小:0.65 第10随机的红包金额大小:1.20 所有红包金额为红包:10.00 手气最佳为:第1个红包,金额为:4.74 第1随机的红包金额大小:0.63 第2随机的红包金额大小:0.33 第3随机的红包金额大小:1.35 第4随机的红包金额大小:1.00 第5随机的红包金额大小:0.70 第6随机的红包金额大小:3.19 第7随机的红包金额大小:0.19 第8随机的红包金额大小:1.50 第9随机的红包金额大小:0.18 第10随机的红包金额大小:0.93 所有红包金额为红包:10.00 手气最佳为:第6个红包,金额为:3.19 第1随机的红包金额大小:1.05 第2随机的红包金额大小:0.68 第3随机的红包金额大小:0.19 第4随机的红包金额大小:1.64 第5随机的红包金额大小:1.64 第6随机的红包金额大小:0.86 第7随机的红包金额大小:0.81 第8随机的红包金额大小:1.06 第9随机的红包金额大小:0.98 第10随机的红包金额大小:1.09 所有红包金额为红包:10.00 手气最佳为:第4个红包,金额为:1.64
[/code]
相关文章推荐
- 微信红包的算法实现探讨(基于PHP)
- PHP实现微信红包金额拆分试玩的算法示例
- 研究微信即时通讯的服务端、朋友圈、红包、推送等方案
- 微信红包算法探究
- 揭秘微信红包架构、抢红包算法和高并发和降级方案
- 代码笔记 | 微信红包算法
- 春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。
- JAVA版的微信红包算法
- 浅谈微信红包的算法
- 微信红包算法
- 揭秘微信红包架构、抢红包算法和高并发和降级方案
- 微信红包随机生成算法php版
- 微信红包算法-php代码
- 揭秘微信红包:架构、抢红包算法、高并发和降级方案
- 微信随机红包数详解和算法代码
- 参考微信红包的抢红包算法
- 微信红包算法
- 微信红包签名算法 C#代码实现
- 微信红包算法遐想
- 算法与数据结构——算法题 21:微信红包(2016腾讯校招笔试题) ? 待解决