After reading the WeChat red envelope grabbing algorithm, you will understand why you are not the luckiest

This article is shared from HUAWEI CLOUD Community " Why is it not always the best luck to grab red envelopes during the Spring Festival? After reading the WeChat grabbing red envelope algorithm, you will understand! ", by XiaoLin_Java.

foreword

From the previous paper red envelopes to the current Internet red envelopes (headed by WeChat red envelopes), grabbing red envelopes is a favorite thing for everyone. Today, we will analyze the algorithm of grabbing red envelopes, some of which are the algorithms of WeChat red envelopes. After reading it, you will know how the best luck is generated!

Algorithm 1: Remaining Amount Randomized Method

Algorithm 1 is not recommended. The full name of Algorithm 1 is the residual amount random method. You can tell from the name that this method is to randomly distribute the remaining amount. Let's look at the code first.

// 分配红包的算法
private static void testPocket(BigDecimal amount, BigDecimal min, BigDecimal num) {
BigDecimal remain = amount.subtract(min.multiply(num));
final Random random = new Random();
final BigDecimal hundred = new BigDecimal("100");
BigDecimal sum = BigDecimal.ZERO;
BigDecimal redpeck ;
for (int i = 0; i < num.intValue(); i++) {
    final int nextInt = random.nextInt(100);
    if (i == num.intValue() - 1) {
        redpeck = remain;
    } else {
        redpeck = new BigDecimal(nextInt).multiply(remain).divide(hundred, 2, RoundingMode.FLOOR);
    }
    if (remain.compareTo(redpeck) > 0) {
        remain = remain.subtract(redpeck);
    } else {
        remain = BigDecimal.ZERO;
    }
    sum = sum.add(min.add(redpeck));
    System.out.println("第" + (i + 1) + "个人抢到红包金额为:" + min.add(redpeck).setScale(2, BigDecimal.ROUND_HALF_UP));
}
System.out.println("红包总额:" + sum.setScale(2, BigDecimal.ROUND_HALF_UP));
}
// 测试代码
public static void main(String[] args) {
    BigDecimal amount = new BigDecimal(100).setScale(2, BigDecimal.ROUND_HALF_UP);
    BigDecimal min = new BigDecimal(0.01).setScale(2, BigDecimal.ROUND_HALF_UP);
    BigDecimal num = new BigDecimal(10).setScale(2, BigDecimal.ROUND_HALF_UP);
    testPocket2(amount,min,num);
}
复制代码

image.png

We can see that this method has obvious flaws, that is, the person who receives the red envelope at the beginning may get the largest amount, and the amount received later gradually becomes smaller, because he randomizes the amount from the remaining amount. of. Obviously, WeChat will definitely not use this method as a red envelope sharing algorithm, otherwise every time there is a red envelope, it is possible to get the best luck by receiving it immediately, but obviously not.

Algorithm 2: Overall random method

The formula of the overall amount random method: 红包总额 * 随机数/随机数总和, the core of this method is to use a random number as the standard for dividing the red envelope, this random number is randomly generated through the Random class. His randomness is relatively large, it seems to be similar to our usual red envelopes, but WeChat red envelopes are not used in this way, because this kind of randomness is too large and it is not very fair.

private static void testPocket2(BigDecimal amount,BigDecimal min ,BigDecimal num){
    final Random random = new Random();
    final int[] rand = new int[num.intValue()];
    BigDecimal sum1 = BigDecimal.ZERO;
    BigDecimal redpeck ;
    int sum = 0;
    for (int i = 0; i < num.intValue(); i++) {
        rand[i] = random.nextInt(100);
        sum += rand[i];
    }
    final BigDecimal bigDecimal = new BigDecimal(sum);
    BigDecimal remain = amount.subtract(min.multiply(num));
    for (int i = 0; i < rand.length; i++) {
        if(i == num.intValue() -1){
            redpeck = remain;
        }else{
            redpeck = remain.multiply(new BigDecimal(rand[i])).divide(bigDecimal,2,RoundingMode.FLOOR);
        }
        if(remain.compareTo(redpeck) > 0){
            remain = remain.subtract(redpeck);
        }else{
            remain = BigDecimal.ZERO;
        }
        sum1= sum1.add(min.add(redpeck)).setScale(2, BigDecimal.ROUND_HALF_UP);
        System.out.println("第"+(i+1)+"个人抢到红包金额为:"+min.add(redpeck).setScale(2, BigDecimal.ROUND_HALF_UP));
    }

    System.out.println("红包总额:"+sum1);
}

// 测试代码
public static void main(String[] args) {
    BigDecimal amount = new BigDecimal(100).setScale(2, BigDecimal.ROUND_HALF_UP);
    BigDecimal min = new BigDecimal(0.01).setScale(2, BigDecimal.ROUND_HALF_UP);
    BigDecimal num = new BigDecimal(10).setScale(2, BigDecimal.ROUND_HALF_UP);
    testPocket2(amount,min,num);
}
复制代码

image.png

His randomness can be described as very high, and it is not the best choice.

Algorithm 3: Secant Method

The secant method refers to imagining the total amount of the red envelope as a long line segment, and the amount each person grabs is a number of sub-line segments split from this main line segment. After all the cutting points are determined, the sub-line segment The length is also determined accordingly. In this way, when everyone comes to grab the red envelope, they only need to receive the red envelope amount equivalent to the length of the sub-line segment in sequence.

image.png

private static void testPocket3(BigDecimal amount, BigDecimal min, BigDecimal num) {
    final Random random = new Random();
    final int[] rand = new int[num.intValue()];
    BigDecimal sum1 = BigDecimal.ZERO;
    BigDecimal redpeck;
    int sum = 0;
    for (int i = 0; i < num.intValue(); i++) {
        rand[i] = random.nextInt(100);
        sum += rand[i];
    }
    final BigDecimal bigDecimal = new BigDecimal(sum);
    BigDecimal remain = amount.subtract(min.multiply(num));
    for (int i = 0; i < rand.length; i++) {
        if (i == num.intValue() - 1) {
            redpeck = remain;
        } else {
            redpeck = remain.multiply(new BigDecimal(rand[i]))
                .divide(bigDecimal, 2, RoundingMode.FLOOR);
        }
        if (remain.compareTo(redpeck) > 0) {
            remain = remain.subtract(redpeck).setScale(2, BigDecimal.ROUND_HALF_UP);
        } else {
            remain = BigDecimal.ZERO;
        }
        sum1 = sum1.add(min.add(redpeck).setScale(2, BigDecimal.ROUND_HALF_UP));
        System.out.println("第" + (i + 1) + "个人抢到红包金额为:" + min.add(redpeck));
    }

    System.out.println("红包总额:" + sum1);
}
// 测试代码
public static void main(String[] args) {
    BigDecimal amount = new BigDecimal(100).setScale(2, BigDecimal.ROUND_HALF_UP);
    BigDecimal min = new BigDecimal(0.01).setScale(2, BigDecimal.ROUND_HALF_UP);
    BigDecimal num = new BigDecimal(10).setScale(2, BigDecimal.ROUND_HALF_UP);
    testPocket2(amount,min,num);
}
复制代码

image.png

His randomness is also relatively large, but his most deadly performance is because he needs to perform the cutting step.

Algorithm 4: Double Mean Method

Algorithm 4 is the algorithm currently used by WeChat red envelopes (rough idea, code simulation), and the calculation formula for the double mean: 2 * 剩余金额/剩余红包数.

  BigDecimal remain = amount.subtract(min.multiply(num));
    final Random random = new Random();
    final BigDecimal hundred = new BigDecimal("100");
    final BigDecimal two = new BigDecimal("2");
    BigDecimal sum = BigDecimal.ZERO;
    BigDecimal redpeck;
    for (int i = 0; i < num.intValue(); i++) {
        final int nextInt = random.nextInt(100);
        if(i == num.intValue() -1){
            redpeck = remain;
        }else{
            redpeck = new BigDecimal(nextInt).multiply(remain.multiply(two).divide(num.subtract(new BigDecimal(i)),2,RoundingMode.CEILING)).divide(hundred,2, RoundingMode.FLOOR);
        }
        if(remain.compareTo(redpeck) > 0){
            remain = remain.subtract(redpeck).setScale(2, BigDecimal.ROUND_HALF_UP);
        }else{
            remain = BigDecimal.ZERO;
        }
        sum = sum.add(min.add(redpeck)).setScale(2, BigDecimal.ROUND_HALF_UP);
        System.out.println("第"+(i+1)+"个人抢到红包金额为:"+min.add(redpeck));
    }
    System.out.println("红包总额:" + sum);
}
复制代码

image.png

It is still better to ensure that the amount of each red envelope is roughly equal, and there will be no extreme situations.

Click Follow to learn about HUAWEI CLOUD's new technologies for the first time~

Guess you like

Origin juejin.im/post/7080343105177665544