抽奖算法 中奖算法 权重随机算法实现 中奖概率实现方式 无需配置中奖概率 自我实现

封装好的工具类

/**
 * 随机工具
 *
 * @author cc
 * @date 2021/5/18
 */
public class RandomUtil {

    private static final int MAX_WEIGHT = 1;

    /**
     * 权重随机算法
     * 比如传入weightArray={1D,2D,3D,4D} 那么100W次结果返回下标0,1,2,3的概率应为10%,20%,30%,40%
     * 比如传入weightArray={1D,2D} 那么100W次结果返回下标0,1的概率应为33.33%,66.67%
     * @param weightArray 权重源数组,不能为空
     * @return 权重数组下标
     */
    public static int weightWinning(double[] weightArray) {
        if (weightArray.length == 0) {
            return -1;
        }
        // hutool
        double randomDouble = cn.hutool.core.util.RandomUtil.randomDouble(MAX_WEIGHT);
        // or java random
        // double randomDouble = new Random().nextDouble()
        double sum = 0D;
        for (double data : weightArray) {
            sum += data;
        }
        int index = 0;
        double curSum = 0D;
        for (double data : weightArray) {
            if (randomDouble < curSum + data / sum) {
                return index;
            } else {
                curSum += data / sum;
                index++;
            }
        }
        return index;
    }
}

原理

我来拿具体的实例来说weightArray={1,2,3,4}来说

randomDouble 取到的是大约等于0小于1的小数,比如这次的随机结果是0.38...,那么返回的本次下标是如何实现的呢

我们把weightArray={1,2,3,4}将线段长度为1的线段等权划分出来4分,下标为0段长为0.1,范围是[0~0.1)一次类推下标1为[0.1~0.3)。。总结来说0~0.1,0.1~0.3,0.3~0.6,0.6~1.0 那么本次0.38坐落在下标为2的线段中,返回结果为2。

这个思想就是想象把一块飞盘按权重划分为不同区域的位置,randomDouble坐落在哪个位置就返回什么结果。

测试

100W次的结果

抽奖算法 中奖算法 权重随机算法实现 中奖概率实现方式 无需配置中奖概率 自我实现_第1张图片

注意

randomDouble 我用的是hutool工具包里单例实现的,尽量避免java实例获取

你可能感兴趣的:(基础,算法,java,算法)