保底抽奖算法
闲来无事,结合之前自己写的权重随机算法和原神的大保底抽奖规则写个简单实现的方法,内容好懂,给出了单元测试,附上代码
import java.util.Arrays;
/**
* 随机工具
*
* @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;
}
/**
* 保底算法
* 将大奖指定为下标1,模拟一下
* @param guarantee 保底次数
* @param total 抽奖次数
* @return 总共中将
*/
public int guaranteedWinning(int guarantee, int total) {
double[] weightArrays = new double[80];
Arrays.fill(weightArrays, 1.0D);
int res = 0;
int cur = 0;
for (int i = 0; i < total; i++) {
int index = cur == guarantee - 1 ? 0 : weightWinning(weightArrays);
if (index == 0) {
res++;
cur = 0;
} else {
cur++;
}
}
return res;
}
@Test
public void cj() {
System.out.println(guaranteedWinning(80, 160));
}
}
说明
我这里抽象了实际,把下标0极为保底奖品,运用到实际具体改,通常是一个用户不同抽奖池对应来分组,简单结合一下就行了