抢红包的红包生成算法

原创 2014年02月18日 22:16:32

过年微信红包很火,最近有个项目也要做抢红包,于是写了个红包的生成算法。


红包生成算法的需求

预先生成所有的红包还是一个请求随机生成一个红包

简单来说,就是把一个大整数m分解(直接以“分为单位,如1元即100)分解成n个小整数的过程,小整数的范围是[min, max]。

最简单的思路,先保底,每个小红包保证有min,然后每个请求都随机生成一个0到(max-min)范围的整数,再加上min就是红包的钱数。

这个算法虽然简单,但是有一个弊端:最后生成的红包可能都是min钱数的。也就是说可能最后的红包都是0.01元的。


另一种方式是预先生成所有红包,这样就比较容易控制了。我选择的是预先生成所有的红包。

理想的红包生成算法

理想的红包生成结果是平均值附近的红包比较多,大红包和小红包的数量比较少。

可以想像下,生成红包的数量的分布有点像正态分布


那么如何实现这种平均线附近值比较多的要求呢?

就是要找到一种算法,可以提高平均值附近的概率。那么利用一种”膨胀“再”收缩“的方式来达到这种效果。

先平方,再生成平方范围内的随机数,再开方,那么概率就不再是平均的了。

具体算法:

public class HongBaoAlgorithm {
	static Random random = new Random();
	static {
		random.setSeed(System.currentTimeMillis());
	}
	
	public static void main(String[] args) {
		long max = 200;
		long min = 1;

		long[] result = HongBaoAlgorithm.generate(100_0000, 10_000, max, min);
		long total = 0;
		for (int i = 0; i < result.length; i++) {
			// System.out.println("result[" + i + "]:" + result[i]);
			// System.out.println(result[i]);
			total += result[i];
		}
		//检查生成的红包的总额是否正确
		System.out.println("total:" + total);

		//统计每个钱数的红包数量,检查是否接近正态分布
		int count[] = new int[(int) max + 1];
		for (int i = 0; i < result.length; i++) {
			count[(int) result[i]] += 1;
		}

		for (int i = 0; i < count.length; i++) {
			System.out.println("" + i + "  " + count[i]);
		}
	}
	
	/**
	 * 生产min和max之间的随机数,但是概率不是平均的,从min到max方向概率逐渐加大。
	 * 先平方,然后产生一个平方值范围内的随机数,再开方,这样就产生了一种“膨胀”再“收缩”的效果。
	 * 
	 * @param min
	 * @param max
	 * @return
	 */
	static long xRandom(long min, long max) {
		return sqrt(nextLong(sqr(max - min)));
	}

	/**
	 * 
	 * @param total
	 *            红包总额
	 * @param count
	 *            红包个数
	 * @param max
	 *            每个小红包的最大额
	 * @param min
	 *            每个小红包的最小额
	 * @return 存放生成的每个小红包的值的数组
	 */
	public static long[] generate(long total, int count, long max, long min) {
		long[] result = new long[count];

		long average = total / count;

		long a = average - min;
		long b = max - min;

		//
		//这样的随机数的概率实际改变了,产生大数的可能性要比产生小数的概率要小。
		//这样就实现了大部分红包的值在平均数附近。大红包和小红包比较少。
		long range1 = sqr(average - min);
		long range2 = sqr(max - average);

		for (int i = 0; i < result.length; i++) {
			//因为小红包的数量通常是要比大红包的数量要多的,因为这里的概率要调换过来。
			//当随机数>平均值,则产生小红包
			//当随机数<平均值,则产生大红包
			if (nextLong(min, max) > average) {
				// 在平均线上减钱
//				long temp = min + sqrt(nextLong(range1));
				long temp = min + xRandom(min, average);
				result[i] = temp;
				total -= temp;
			} else {
				// 在平均线上加钱
//				long temp = max - sqrt(nextLong(range2));
				long temp = max - xRandom(average, max);
				result[i] = temp;
				total -= temp;
			}
		}
		// 如果还有余钱,则尝试加到小红包里,如果加不进去,则尝试下一个。
		while (total > 0) {
			for (int i = 0; i < result.length; i++) {
				if (total > 0 && result[i] < max) {
					result[i]++;
					total--;
				}
			}
		}
		// 如果钱是负数了,还得从已生成的小红包中抽取回来
		while (total < 0) {
			for (int i = 0; i < result.length; i++) {
				if (total < 0 && result[i] > min) {
					result[i]--;
					total++;
				}
			}
		}
		return result;
	}

	static long sqrt(long n) {
		// 改进为查表?
		return (long) Math.sqrt(n);
	}

	static long sqr(long n) {
		// 查表快,还是直接算快?
		return n * n;
	}
	
	static long nextLong(long n) {
		return random.nextInt((int) n);
	}

	static long nextLong(long min, long max) {
		return random.nextInt((int) (max - min + 1)) + min;
	}
}

统计了下生成的结果,还是比较符合要求的。




版权声明:本文为博主原创文章,未经博主允许不得转载。

抢红包算法

#include #include #include #include   int main() {        floata[11];//保存10个红包金额        f...
  • qq_38632614
  • qq_38632614
  • 2017年06月01日 10:17
  • 337

抢红包算法(c语言版)

1、算法背景: 大家知道,微信拼手气红包和普通红包两种。普通红包每个人抢到的金额是固定的(总额的平均数),拼手气红包是随机金额(每个人抢到的是随机的,差别可能非常大,有的人抢到的是1分,有的...
  • qq_38177302
  • qq_38177302
  • 2018年01月04日 09:59
  • 194

抢红包的红包生成算法

本人小菜鸟一只,为了自我学习和交流PHP(jquery,linux,lamp,shell,javascript,服务器)等一系列的知识,小菜鸟创建了一个群。希望光临本博客的人可以进来交流。寻求共同发展...
  • yafei450225664
  • yafei450225664
  • 2015年09月21日 11:21
  • 2437

微信红包算法?

作者:匿名用户 链接:https://www.zhihu.com/question/22625187/answer/40041558 来源:知乎 著作权归作者所有,转载请联系作者获得授权。 ...
  • z69183787
  • z69183787
  • 2016年08月31日 21:54
  • 1634

微信抢红包的算法实现(C++)

目前只能实现对于整数的钱数的红包的实现,经过随机数从而实现随机人抢红包的算法 /* vs 2013 wk */ #include #include #include #in...
  • kai8wei
  • kai8wei
  • 2016年07月04日 17:28
  • 2742

揭秘微信红包:架构、抢红包算法、高并发和降级方案

转载自:http://www.tuicool.com/articles/zQf6zq 编者按 与传统意义上的红包相比,近两年火起来的“红包”,似乎才是如今春节的一大重头戏。历经上千年时代传...
  • lkx94
  • lkx94
  • 2016年12月20日 09:19
  • 1304

php固定红包 + 随机红包算法

1 需求 CleverCode最近接到一个需求,需要写一个固定红包 + 随机红包算法。 1 固定红包就是每个红包金额一样,有多少个就发多少个固定红包金额就行。 2 随机红包的需求是。比如红包总金额5元...
  • CleverCode
  • CleverCode
  • 2016年11月20日 12:39
  • 7308

微信红包随机生成算法(PHP版)

最近看了一篇关于微信红包随机的业务,把代码沾给大家 最近在研究发红包的功能,于是写了个红包的生成算法。   红包生成算法的需求 预先生成所有的红包还是一个请求随机生成一...
  • chen529834149
  • chen529834149
  • 2017年08月10日 10:32
  • 265

java实现微信红包随机算法

import java.util.ArrayList; import java.util.List; /** * Created by Spirit on 2017/1/23. */ publi...
  • Forever_Cvank
  • Forever_Cvank
  • 2017年01月23日 13:41
  • 2424

微信红包随机生成算法(PHP版)

/**  * 求一个数的平方  * @param $n  */  function sqr($n){      return $n*$n;  }    /** * 生产min和max之间的随机数,但是...
  • qq_21938447
  • qq_21938447
  • 2015年07月31日 10:42
  • 2678
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:抢红包的红包生成算法
举报原因:
原因补充:

(最多只允许输入30个字)