js写中奖概率

140 阅读3分钟

结论:

在网上找怎么写,找到个很好的例子,这个逻辑很有启发,但是写完调试发现逻辑是有问题的,然后进行了修正,希望大家用时候注意下。

找到的百度文章 点击查看

过程:

诉求是控制中奖的概率,比如随机给用户积分,需要控制每种积分概率,最低是1分。同样的这个可以类比奖品和未中奖。给的不同积分就是不同等级的奖品,1分就是未中奖

积分654321
概率0.52.55101567

根据网上例子写出来代码是

const priceArr = [6, 5, 4, 3, 2, 1]; //奖品数组,从大到小
const priceWeight = [0.5, 2.5, 5, 10, 15, 67]; //对应位置的概率
randomPrize(prizeArr, weightArr) {
    let weightSum = weightArr.reduce((a, b) => {
      return a + b;
    }, 0);
    const random = Math.random() * weightSum;
    const concatWeightArr = weightArr.concat(random);
    const sortedWeightArr = concatWeightArr.sort((a, b) => {
      return a - b;
    });
    let randomIndex = sortedWeightArr.indexOf(random);
    randomIndex = Math.min(randomIndex, prizeArr.length - 1);
    return prizeArr[randomIndex];
}

思路:

1、权重求和

2、随机从0到权重和之间的数字

3、把随机的数字放到权重数组中

4、新生成的权重数字从小到大排序

5、从新权重数组中找到随机数的位置(防止位置超过奖品数组的大小,超过就设置最后一个)

6、最后拿位置去奖品数组中获取奖品

用例结果

执行1000次

积分654321
期望(%)0.52.55101567
实际次数(次)727315245838
实际概率(%)0.72.73.15.24.583.8

执行10000次

积分654321
期望(%)0.52.55101567
实际次数(次)481912795035068473
实际概率(%)0.481.912.795.035.0684.73

执行100000次

积分654321
期望(%)0.52.55101567
实际次数(次)511203724995033501684904
实际概率(%)0.5112.0372.4995.0335.01684.904

分析:

1、结果看其实就第一个基本接近,其他都是不准的。

2、代码里weightSum咋算都是100。本来就是按照100分配的。

优化代码如下:

const priceArr = [6, 5, 4, 3, 2, 1]; //奖品数组,从大到小
const priceWeight = [0.5, 2.5, 5, 10, 15, 67]; //对应位置的概率
randomPrize(prizeArr, weightArr) {
    const newWeightArr = []; //新排序数组
    //转化实际位置的数字
    weightArr.reduce((a, b) => {
      newWeightArr.push(a + b);
      return a + b;
    }, 0);
    const weightNum = 100;
    const random = Math.random() * weightNum;
    const concatWeightArr = newWeightArr.concat(random);
    const sortedWeightArr = concatWeightArr.sort((a, b) => {
      return a - b;
    });
    let randomIndex = sortedWeightArr.indexOf(random);
    //去除 randomIndex = Math.min(randomIndex, prizeArr.length - 1);
    return prizeArr[randomIndex];
}

用例结果

执行1000次

积分654321
期望(%)0.52.55101567
实际次数(次)52348105127692
实际概率(%)0.52.34.810.512.769.2

执行10000次

积分654321
期望(%)0.52.55101567
实际次数(次)3723953598715126690
实际概率(%)0.372.395.359.8715.1266.9

执行100000次

积分654321
期望(%)0.52.55101567
实际次数(次)5052453499999361503167076
实际概率(%)0.5052.4534.9999.93615.03167.076

分析:

基本符合预期的。

总结:

现成的是方便,但是要用前要思考,结合实际,弄懂原理。