Java抢红包的红包生成算法

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

红包生成算法的需求

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

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

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

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

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

理想的红包生成算法

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

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

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

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

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

具体算法:

public class HongBaoAlgorithm {
  static Random random = new Random();
  static {
    randomsetSeed(SystemcurrentTimeMillis());
  } 

  public static void main(String[] args) {
    long max = 200;
    long min = 1; 

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

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

    for (int i = 0; i < countlength; i++) {
      Systemoutprintln("" + 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 < resultlength; 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 < resultlength; i++) {
        if (total > 0 && result[i] < max) {
          result[i]++;
          total--;
        }
      }
    }
    // 如果钱是负数了,还得从已生成的小红包中抽取回来
    while (total < 0) {
      for (int i = 0; i < resultlength; i++) {
        if (total < 0 && result[i] > min) {
          result[i]--;
          total++;
        }
      }
    }
    return result;
  } 

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

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

  static long nextLong(long n) {
    return randomnextInt((int) n);
  } 

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java实现仿微信红包分配规则

    最近过年发红包拜年成为一种新的潮流,作为程序猿对算法的好奇远远要大于对红包的好奇,这里介绍一种自己想到的一种随机红包分配策略,还请大家多多指教. 算法介绍 一.红包金额限制 对于微信红包,我们知道没人随机的最小红包是1分,最大金额是200元,这里我们同样来设置红包的范围,下面代码我们统一金钱的单位为分. //最小红包额度 private static final int MINMONEY = 1; //最大红包额度 private static final int MAXMONEY = 200

  • java调用微信现金红包接口的心得与体会总结

    这几天看了下之前写的有关微信支付的博客,看的人还是挺多的,看了下留言不知道是因为博客写的不够细还是什么情况,大多都找我要源码,我觉得吧程序员还是需要有这么一个思考的过程,因此没直接给源码,俗话说"授人以鱼不如授人以渔".因此希望看文章的同时也花一点时间自己亲自敲一敲代码.好了废话不多说这次来分享微信现金红包接口的使用. 下面是微信开发文档对现金红包的介绍: 现金红包,是微信支付商户平台提供的营销工具之一,上线以来深受广大商户与用户的喜爱.商户可以通过本平台向微信支付用户发放现金红包.用

  • java模拟微信抢红包的实例代码

    java简单模拟微信抢红包功能,本例发100元红包,有10个人抢,为了尽可能的公平,每个人的红包金额都要随机(保证结果的不确定性,本例抢红包的次序与红包金额匹配也随机),就是不能出现部分红包偏大部分偏小的情况,在区间0~100上随机生成9个节点,加0和100共11个节点按从小到大排序,各节点之间的差值就是红包金额,保证了红包金额之和等于100. public static void main(String[] args) { // 发100元红包,10人抢 // TODO Auto-genera

  • java 微信随机红包算法代码实例

    前几天的一个晚上突然想到微信红包应该有一个随机算法,就自己试着写了下,也不知道对不对,看了看网上的说法,好像到现在为止官方也没有给出一个确切的算法,只好在这里献丑了,先贴出代码: public static double [] getMoney(double money, int num){ Random r = new Random(); DecimalFormat format = new DecimalFormat(".##"); double middle = Double.p

  • java微信红包实现算法

    随着目前微信越来越火,所以研究微信的人也就越来越多,这不前一段时间,我们公司就让我做一个微信公众号中问卷调查发红包功能,经过一段时间的研究,把功能完成,里面主要的实现步骤都是按照微信公众号开发文档来的,很详细,在整个过程唯有红包算法需要仔细编写,因为毕竟涉及到钱,所以得小心,而且不仅微信中需要发红包,我们在做APP时可能也会遇到需要发红包的功能,所以这里列出红包的核心算法,供大家一起学习研究. public static List getRed(int number,float total,do

  • 微信随机生成红包金额算法java版

    最近几年玩得最疯狂的应该是发红包了,尤其是过年的时候特别受欢迎,下面写了红包的随机算法,其实挺简单的,仅是提供一种思路,希望可以给大家一些启发. public class WxAlgorithm{ /** * @param moneySum 输入总金额 * @param redNum 输入红包数量 */ private static void wxAlgorithm(double moneySum, int redNum) { // 设置最小的金额 double moneyMin = 0.01;

  • JAVA实现简单抢红包算法(模拟真实抢红包)

    闲来无事,最近项目需求要写出用户登录首页来发现金红包,没有限额.我就自己稍微计算了一下如果有限额该怎么写.觉得这样与微信红包差不多.等项目需求完成以后.正好来博客贴一下我自己写的拆红包算法.个人觉得这个算法比较模拟现实抢红包规则.废话少说.先贴代码; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.ut

  • Java微信支付-微信红包

    微信红包的使用已经很广泛,本篇文章介绍了微信发红包的实例,需要有认证的公众号,且开通了微信支付,商户平台且开通了现金红包的权限即可. https://pay.weixin.qq.com商户登陆地址.选择查看营销中心的现金红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_1 现金红包的官网文档说明 先看几个图 简单的测试.前提需要你去商户平台先充值.不支持预支付.本文只是总结微信现金红包接口的调用与

  • Java抢红包的红包生成算法

    马上过年了.过年微信红包很火,最近有个项目也要做抢红包,于是写了个红包的生成算法. 红包生成算法的需求 预先生成所有的红包还是一个请求随机生成一个红包 简单来说,就是把一个大整数m分解(直接以"分为单位,如1元即100)分解成n个小整数的过程,小整数的范围是[min, max]. 最简单的思路,先保底,每个小红包保证有min,然后每个请求都随机生成一个0到(max-min)范围的整数,再加上min就是红包的钱数. 这个算法虽然简单,但是有一个弊端:最后生成的红包可能都是min钱数的.也就是说可能

  • Java一个简单的红包生成算法

    一个简单的红包生成算法,代码如下: /** * 红包 * @param n * @param money 单位:分 * @return **/ public static double[] redPacket(int n, double money) { // 红包结果 double[] result = new double[n]; // 随机数 double[] randNum = new double[n]; // 随机总数 double randSum = 0; // 保证每个人都分到一

  • java中全排列的生成算法汇总

    全排列的生成算法就是对于给定的字符集,用有效的方法将所有可能的全排列无重复无遗漏地枚举出来.任何n个字符集的排列都可以与1-n的n个数字的排列一一对应,   因此在此就以n个数字的排列为例说明排列的生成法. n个字符的全体排列之间存在一个确定的线性顺序关系.所有的排列中除最后一个排列外,都有一个后继:除第一个排列外,都有一个前驱.每个排列的后继都可以从它的前驱经过最少的变化而得到,全排列的生成算法就是从第一个排列开始逐个生成所有的排列的方法. 全排列的生成法通常有以下几种: 字典序法   递增进

  • 微信随机生成红包金额算法php版

    最近在研究发红包的功能,于是写了个红包的生成算法. 红包生成算法的需求 预先生成所有的红包还是一个请求随机生成一个红包 简单来说,就是把一个大整数m分解(直接以"分为单位,如1元即100)分解成n个小整数的过程,小整数的范围是[min, max]. 最简单的思路,先保底,每个小红包保证有min,然后每个请求都随机生成一个0到(max-min)范围的整数,再加上min就是红包的钱数. 这个算法虽然简单,但是有一个弊端:最后生成的红包可能都是min钱数的.也就是说可能最后的红包都是0.01元的. 另

  • java实现的AES秘钥生成算法示例

    本文实例讲述了java实现的AES秘钥生成算法.分享给大家供大家参考,具体如下: import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; public class Test { public static void main(String[] args) { g

  • 微信红包随机生成算法php版

    想了想,自己写写php版的微信红包随机生成算法,能不能实现类似的功能(其实也不敢说是算法). // $bonus_total 红包总金额 // $bonus_count 红包个数 // $bonus_type 红包类型 1=拼手气红包 0=普通红包 function randBonus($bonus_total=0, $bonus_count=3, $bonus_type=1){ $bonus_items = array(); // 将要瓜分的结果 $bonus_balance = $bonus

  • python 实现红包随机生成算法的简单实例

    实例如下: </pre><pre name="code" class="python">#! /usr/bin/python # -*- coding: utf-8 -*- import random class CDispatch: def __init__(self,sum,count): self.sum = sum self.count=count #print 'init here sum =',sum,',count =',cou

  • Java基于深度优先遍历的随机迷宫生成算法

    这两天因为要做一个随机的地图生成系统,所以一直在研究随机迷宫生成算法,好吧,算是有一点小小的成果. 随机迷宫生成我自己的理解简而言之分为以下几步: 1.建立一张地图,我用的二维数组表示,地图上全是障碍物.然后再创建一个用来表示每个格子是否被访问过的二维数组.再创建一个用来表示路径的栈结构. 2.随机选择地图上的一点,呃为了方便我初始点直接取的是左上角即坐标表示为0,0的格子.终点的话因为不涉及到交互就暂时没有. 3.查找当前格子的邻接格(注意,这里的邻接格子都是还未被访问的,下面的代码里有写).

  • java实现微信红包 拼手气红包

    本文实例为大家分享了java实现微信红包的具体代码,供大家参考,具体内容如下 要求 基于BigDecimal类实现微信红包算法的功能,比如设置红包总金额,然后设置需要生成的红包个数,为每个红包随机指定金额,最低不能低于0.01元,要求: 1.每个红包金额随机指定 2.每个红包金额不能低于0.01元 3.要求每个红包的金额之和恰好等于总金额 4.如果平均每个红包的金额不足0.01元时抛出一个RedPacketException,提示每个红包金额不能少于0.01元 实现方法 该题主要考察java常用

随机推荐