如何向小朋友解释抽奖的游戏抽奖概率问题退款

最近接触到一个抽奖需求,加上平时玩的暗黑3很少掉暗金装备,就抽空学习下这类概率问题,暂时按网络称为掉宝类型概率。
例如游戏中打败一个boss,会掉落下面其中一个物品,而每个物品都有一定概率:
1. 靴子 20%
2. 披风 25%
3. 饰品 10%
4. 双手剑 5%
5. 金币袋 40%
现在的问题就是如何根据概率掉落一个物品给玩家。
一. 一般:生成一个列表,分成几个区间,例如列表长度100,1-20是靴子的区间,21-45是披风的区间等,然后随机从100取出一个数,看落在哪个区间。算法时间复杂度:预处理O(MN),随机数生成O(1),空间复杂度O(MN),其中N代表物品种类,M则由最低概率决定。
二、离散算法:也就是上面的改进,竟然1-20都是靴子,21-45都是披风,那抽象成小于等于20的是靴子,大于20且小于等于45是披风,就变成几个点[20,45,55,60,100],然后也是从1到99随机取一个数R,按顺序在这些点进行比较,知道找到第一个比R大的数的下标,比一般算法减少占用空间,还可以采用二分法找出R,这样,预处理O(N),随机数生成O(logN),空间复杂度O(N)。
请点击查看详细:
三、Alias Method
Alias Method就不太好理解,实现很巧妙,推荐先看看这篇文章:
大致意思:把N种可能性拼装成一个方形(整体),分成N列,每列高度为1且最多两种可能性,可能性抽象为某种颜色,即每列最多有两种颜色,且第n列中必有第n种可能性,这里将第n种可能性称为原色。
想象抛出一个硬币,会落在其中一列,并且是落在列上的一种颜色。这样就得到两个数组:一个记录落在原色的概率是多少,记为Prob数组,另一个记录列上非原色的颜色名称,记为Alias数组,若该列只有原色则记为null。
之前的例子,为了便于演示换成分数
1. 靴子 20% -& 1/4
2. 披风 25% -& 1/5
3. 饰品 10% -& 1/10
4. 双手剑 5% -& 1/20
5. 金币袋 40% -& 2/5
然后每个都乘以5(使每列高度为1),再拼凑成方形
拼凑原则:每次都从大于等于1的方块分出一小块,与小于1的方块合成高度为1
由上图方形可得到两个数组:
Prob: [3/4, 1/4, 1/2, 1/4, 1]
Alias: [4, 4, 0, 1, null] (记录非原色的下标)
之后就根据Prob和Alias获取其中一个物品
随机产生一列C,再随机产生一个数R,通过与Prob[C]比较,R较大则返回C,反之返回Alias[C]。
Alias Method 复杂度:预处理O(NlogN),随机数生成O(1),空间复杂度O(2N)
实现Alias Method
@desc 拼凑,获得Prob和Alias数组
@param array $data
@param array $prob
@param array $alias
init(array
= count($data);
&&&&$small
= array();
&&&&&&&&$data[$i]
= $data[$i]
// 扩大倍数,使每列高度可为1
&&&&&&&&/**
分到两个数组,便于组合 */
&&&&&&&&if
($data[$i]
&&&&&&&&&&&&$small[]
&&&&&&&&&&&&$large[]
将超过1的色块与原色拼凑成1 */
(!empty($small)
&& !empty($large))
&&&&&&&&$n_index
= array_shift($small);
&&&&&&&&$a_index
= array_shift($large);
&&&&&&&&$prob[$n_index]
= $data[$n_index];
&&&&&&&&$alias[$n_index]
= $a_index;
&&&&&&&&//
重新调整大色块
&&&&&&&&$data[$a_index]
= ($data[$a_index]
+ $data[$n_index])
&&&&&&&&if
($data[$a_index]
&&&&&&&&&&&&$small[]
= $a_index;
&&&&&&&&&&&&$large[]
= $a_index;
剩下大色块都设为1 */
(!empty($large))
&&&&&&&&$n_index
= array_shift($large);
&&&&&&&&$prob[$n_index]
一般是精度问题才会执行这一步 */
(!empty($small))
&&&&&&&&$n_index
= array_shift($small);
&&&&&&&&$prob[$n_index]
@desc 获取某种物品
@param array $prob
@param array $alias
@return int
generation($prob,
= count($prob)
&&&&$MAX_P
= 100000; // 假设最小的几率是万分之一
&&&&$coin_toss
= rand(1, $MAX_P)
// 抛出硬币
&&&&&&&&$col
= rand(0, $nums);
// 随机落在一列
&&&&$b_head
= ($coin_toss
& $prob[$col])
? TRUE : FALSE; // 判断是否落在原色
&&&&return
: $alias[$col];
= array(0.25,
0.2, 0.1, 0.05, 0.4);
= array();
init($data,
= generation($prob,
= array(0,
0, 0, 0, 0);
& 10000; $i++)
&&&&$result
= generation($prob,
&&&&$count[$result]++;
print_r($count);
阅读(...) 评论()关于怎么设置抽奖概率的问题,谢谢_百度知道
关于怎么设置抽奖概率的问题,谢谢
...问一个问题,关于抽奖概率的设置,和原理,假如一共有40W用户每天可以参加3次,持续30天,(中奖了,就结束抽奖资格)有320个奖品,分为5个等级,要怎么设置抽奖概率用什么方式实现...
... 问一个
问题, 关于抽奖概率的 设置, 和 原理,假如 一共有 40W用户
每天可以 参加3次,持续30天, (中奖了,就结束抽奖资格)有320个奖品 ,分为5个等级,
要怎么设置 抽奖概率 用什么方式 实现/??
可以预定义一个数,然后根据百分比计算各自的门槛值。如下:(注意:概率需要从小到大排列,因为用if判断的问题。)#define BASE_NUMBER 32767#define BASE_DIV
100#define RATE1
1#define RATE2
5#define RATE3
20#define RATE4
74 int var1, var2, var3, var4;main() else if ( rand &= var2 )
else if ( rand &= var3 )
else ...} 如上,只需要改变BASE_DIV 和RATE1 2 3 4就能控制
为你推荐:
其他类似问题
您可能关注的内容
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
【2017年整理】毕业论文·抽奖活动中的概率问题.doc 12页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
【2017年整理】毕业论文·抽奖活动中的概率问题
你可能关注的文档:
··········
··········
上饶师范学院
抽奖活动中的概率问题
学生姓名:
数学与计算机科学学院
数学与应用数学
指导教师:
二零一六年 五月
随着现代生活节奏的不断加快,我们身边逐渐出现了许多形形色色的抽奖活动,里面也涉及到了各种概率问题。本文通过对不同类型的抽奖活动中所涉及到的概率问题进行详细的解析,让大家可以清楚地看到活动的本身,明白活动的实质,然后理性地进行参与和选择。
蒙特难题;条件概率;免费抽奖;彩票
蒙特难题 1
1.1蒙特难题的来源 1
1.2蒙特难题的看法及解析 1
1.3蒙特难题的影响 2
抽奖过程中的条件概率问题 2
免费抽奖活动中的陷阱 3
3.1活动的玩法和奖品介绍 4
3.2陷阱原由及详解 4
彩票中奖的概率问题 6
4.1大乐透的玩法介绍 6
4.2彩票的中奖概率分析 7
参考文献 9
抽奖活动中的概率问题
随着社会的发展,当今人类的生活也逐渐变得复杂起来,所遇到的问题也越来越多,而在这些问题中绝大部分其实都是数学上的问题。概率论是数学的一个分支,概率论思想也早已渗透到了我们生活中的方方面面,我们也会经常用到概率论的知识来解决生活中遇到的实际问题。而在这些问题中,抽奖类的问题尤发显得突出,所涉及到的概率知识也更广更多。现在,我们用概率论知识来分析下我们生活中常碰到的几类抽奖问题。
1.1蒙特难题的来源
蒙特?霍尔是美国的一位电视游戏节目主持人,他曾在多年以前主持了一档名为Let’s Make a Deal的节目。这个节目规则:蒙特会向选手展示三扇关着的门,在这三扇门中,其中有一扇门的后面是有一辆小轿车的,而另外两扇门的后面都是空房间。门后面到底是什么选手并不知情,但蒙特却是事先知道的。选手站在三扇关着的门前,然后进行游戏。
游戏共分为三个步骤:
1. 让选手选定一扇自己认为门后面是有小轿车的门,选定后门先不打开,让其保持着仍然关闭着的状态。
2. 蒙特紧接着打开选手选剩下的两扇门中门后面是空房间的一扇门。
3. 然后蒙特会给选手俩个选择:一是坚持打开自己原先选定的那扇门;二是放弃自己原先的选择,更改为去打开另一扇仍然关闭着的门。
选手最终选定后,蒙特便会打开那扇门。如果门后面的是小轿车,那么选手便胜利,赢得了这辆小轿车,反之则一无所有。那么我们该如何选择才会有更大的几率赢得小轿车?在蒙特打开一扇门之后,我们是应该坚持自己原先的选择呢,还是要改变已经做好的选择,反而去打开另一扇门。这便是概率问题上的一个著名难题——蒙特难题(Monty Hall problem)。
1.2蒙特难题的看法及解析
对于蒙特门难题的看法,普遍有两种观点:1:假设选手第一次选择的是A门的话,那么中奖的概率为,当蒙特打开B,C门中没有奖的一扇门后,选手若改选B,C门中没有打开的一扇门,相当于选择了B,C两扇门,此时选手的中奖概率为,所以选手应该改选;2:选手任意打开一扇门的中奖概率为,当蒙特打开另两扇门中没有奖的一扇门后,相当于选手在剩余的两扇门中任选一扇门,中奖的概率都为,所以改不改选都一样。
其实,这个问题我们可以用概率的思想来进行分析。事实上这就是一个把古典型概率问题变成了条件概率问题。选手在三扇门中任选一扇门是一个古典型概率问题,每个选择并且中奖的概率是等可能的,都为,即。在蒙特打开了一扇空门之后,其造成的结果对选手坚持自己的原先的选择是没有任何影响的,因为这是选手在获取蒙特打开空门这个信息之前的选择。但是如果选手改选为另一扇门的话,那么这个概率问题则变成了条件概率问题.
条件概率是指在“已知事件B发生”的附加前提下,求另一个事件A所发生概率,即这个概率被称为B发生的前提条件下事件A发生的条件概率,并记作P(A|B)。
在这个问题中,事件 B 为蒙特已经打开了一扇门后面是空房间的情况, 而事件 A 则为选手更改了自己的原先的选择,去打开剩下一扇关着的门,结果反而门后面是一辆小轿车的情况。所以有:
解: 不妨设选手 A、B、C三人分别对应选择了A门、 B门和C门,则有:
正在加载中,请稍后...毕业论文?抽奖活动中的概率问题_百度文库
您的浏览器Javascript被禁用,需开启后体验完整功能,
享专业文档下载特权
&赠共享文档下载特权
&100W篇文档免费专享
&每天抽奖多种福利
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
毕业论文?抽奖活动中的概率问题
阅读已结束,下载本文需要
定制HR最喜欢的简历
下载文档到电脑,同时保存到云知识,更方便管理
加入VIP
还剩9页未读,
定制HR最喜欢的简历
你可能喜欢Java抽奖概率算法
抽到的概率
本站VIP一年
100元手机话费
数据很简单,那么就直接看代码了
* @author:rex
* @date:日
* @version:1.0
public class Gift {
private String gitfId;
private String giftN
public Gift(int index, String gitfId, String giftName, double probability) {
this.index =
this.gitfId = gitfId;
this.giftName = giftN
this.probability =
public int getIndex() {
public void setIndex(int index) {
this.index =
public String getGitfId() {
return gitfId;
public void setGitfId(String gitfId) {
this.gitfId = gitfId;
public String getGiftName() {
return giftN
public void setGiftName(String giftName) {
this.giftName = giftN
public double getProbability() {
public void setProbability(double probability) {
this.probability =
public String toString() {
return "Gift [index=" + index + ", gitfId=" + gitfId + ", giftName=" + giftName + ", probability="
+ probability + "]";
* 不同概率抽奖工具包
* @author:rex
* @date:日
* @version:1.0
public class LotteryUtil {
* @param orignalRates 原始的概率列表,保证顺序和实际物品对应
* @return 物品的索引
public static int lottery(List&Double& orignalRates) {
if (orignalRates == null || orignalRates.isEmpty()) {
return -1;
int size = orignalRates.size();
// 计算总概率,这样可以保证不一定总概率是1
double sumRate = 0d;
for (double rate : orignalRates) {
sumRate +=
// 计算每个物品在总概率的基础下的概率情况
List&Double& sortOrignalRates = new ArrayList&Double&(size);
Double tempSumRate = 0d;
for (double rate : orignalRates) {
tempSumRate +=
sortOrignalRates.add(tempSumRate / sumRate);
// 根据区块值来获取抽取到的物品索引
double nextDouble = Math.random();
sortOrignalRates.add(nextDouble);
Collections.sort(sortOrignalRates);
return sortOrignalRates.indexOf(nextDouble);
public static int getJD(List&Double& orignalRates) {
if (orignalRates == null || orignalRates.isEmpty()) {
return -1;
int size = orignalRates.size();
// 计算总概率,这样可以保证不一定总概率是1
double sumRate = 0d;
for (double rate : orignalRates) {
sumRate +=
// 计算每个物品在总概率的基础下的概率情况
List&Double& sortOrignalRates = new ArrayList&Double&(size);
Double tempSumRate = 0d;
for (double rate : orignalRates) {
tempSumRate +=
sortOrignalRates.add(tempSumRate / sumRate);
// 根据区块值来获取抽取到的物品索引
double nextDouble = Math.random();
sortOrignalRates.add(nextDouble);
Collections.sort(sortOrignalRates);
return sortOrignalRates.indexOf(nextDouble);
* 不同概率抽奖
* @author:rex
* @date:日
* @version:1.0
public class LotteryTest {
public static void main(String[] args) {
List&Gift& gifts = new ArrayList&Gift&();
// 序号==物品Id==物品名称==概率
gifts.add(new Gift(1, "P1", "物品1", 0.2d));
gifts.add(new Gift(2, "P2", "物品2", 0.2d));
gifts.add(new Gift(3, "P3", "物品3", 0.4d));
gifts.add(new Gift(4, "P4", "物品4", 0.3d));
gifts.add(new Gift(5, "P5", "物品5", 0d));
gifts.add(new Gift(6, "P6", "物品6", -0.1d));
gifts.add(new Gift(7, "P7", "物品7", 0.008d));
List&Double& orignalRates = new ArrayList&Double&(gifts.size());
for (Gift gift : gifts) {
double probability = gift.getProbability();
if (probability & 0) {
probability = 0;
orignalRates.add(probability);
// statistics
Map&Integer, Integer& count = new HashMap&Integer, Integer&();
double num = 1000000;
for (int i = 0; i & i++) {
int orignalIndex = LotteryUtil.lottery(orignalRates);
Integer value = count.get(orignalIndex);
count.put(orignalIndex, value == null ? 1 : value + 1);
for (Entry&Integer, Integer& entry : count.entrySet()) {
System.out.println(gifts.get(entry.getKey()) + ", count=" + entry.getValue() + ", probability="
+ entry.getValue() / num);
Gift [index=1, gitfId=P1, giftName=物品1, probability=0.2], count=180854, probability=0.180854
Gift [index=2, gitfId=P2, giftName=物品2, probability=0.2], count=180789, probability=0.180789
Gift [index=3, gitfId=P3, giftName=物品3, probability=0.4], count=361198, probability=0.361198
Gift [index=4, gitfId=P4, giftName=物品4, probability=0.3], count=269950, probability=0.26995
Gift [index=7, gitfId=P7, giftName=物品7, probability=0.008], count=7209, probability=0.007209
不同概率的抽奖原理很简单
就是把0到1的区间分块,而分块的依据就是物品占整个的比重,再根据随机数种子来产生0-1中间的某个数,来判断这个数是落在哪个区间上,而对应的就是抽到了那个物品。随机数理论上是概率均等的,产生的每个数理论上也应该概率均等,那么相应的区间所含数的多少就体现了抽奖物品概率的不同。(p.s. 当然数目是数不清楚的,具体抽象话了点)
这个实例的数据可以说明
1. 概率可以是负数和0,当然实际上中应该不会(p.s. 正常情况下可能真的有0,比如抽个iphone5,当然是抽不到的了,这个时候,构建礼物(List gifts)的时候最好就不要加这个进去),还有可以把负数的处理放到抽奖工具类(LotteryUtil)中;
2. 所有礼物加起来的概率可以不是1,可以认为这里的概率是一个权重。
Copyright (C) , All Rights Reserved.
版权所有 闽ICP备号
processed in 0.042 (s). 13 q(s)}

我要回帖

更多关于 游戏抽奖概率问题退款 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信