有几率的红包抽奖怎么做,用ppt或java软件?

有几率的红包抽奖怎么做,用ppt或java软件?,第1张

Random类有方法可以调用。模型应该是0到1(两边都包含)的一个线段,然后在这个线段上设定奖品对应的概率(比如0-0.2对应第一个奖品,0.2-0.5对应第二个奖品,以此类推),最后随机一次看得到的数字落在哪个区间,实现抽奖

import java.util.ArrayList

import java.util.List

import java.util.Random

/**

* 抽奖工具类,概率和可以不等于1

* 概率为百分数去掉百分号的部分,如10%,则为10

* 抽奖 *** 作如下:

* 1.输入抽奖概率集合,【抽奖概率集合为{10.0, 20.0, 30.0}】

* 2.生成连续集合,       【生成的连续集合为{(0.0, 10.0],(10.0, 30.0],(30.0, 60.0]}】

* 3.生成随机数,          【生成方法为 random.nextDouble() * maxElement】

* 4.判断随机数在哪个区间内,返回该区间的index【生成了随机数12.001,则它属于(10.0, 30.0],返回 index = 1】

*

*/

public class LotteryUtil {

/**

* 定义一个连续集合

* 集合中元素x满足:(minElement,maxElement]

* 数学表达式为:minElement < x <= maxElement

*

*/

public class ContinuousList {

private double minElement

private double maxElement

public ContinuousList(double minElement, double maxElement){

if(minElement > maxElement){

throw new IllegalArgumentException("区间不合理,minElement不能大于maxElement!")

}

this.minElement = minElement

this.maxElement = maxElement

}

/**

* 判断当前集合是否包含特定元素

* @param element

* @return

*/

public boolean isContainKey(double element){

boolean flag = false

if(element > minElement && element <= maxElement){

flag = true

}

return flag

}

}

private List<ContinuousList> lotteryList   //概率连续集合

private double maxElement                  //这里只需要最大值,最小值默认为0.0

/**

* 构造抽奖集合

* @param list 为奖品的概率

*/

public LotteryUtil(List<Double> list){

lotteryList = new ArrayList<ContinuousList>()

if(list.size() == 0){

throw new IllegalArgumentException("抽奖集合不能为空!")

}

double minElement = 0d

ContinuousList continuousList = null

for(Double d : list){

minElement = maxElement

maxElement = maxElement + d

continuousList = new ContinuousList(minElement, maxElement)

lotteryList.add(continuousList)

}

}

/**

* 进行抽奖 *** 作

* 返回:奖品的概率list集合中的下标

*/

public int randomColunmIndex(){

int index = -1

Random r = new Random()

double d = r.nextDouble() * maxElement  //生成0-1间的随机数

if(d == 0d){

d = r.nextDouble() * maxElement     //防止生成0.0

}

int size = lotteryList.size()

for(int i = 0 i < size i++){

ContinuousList cl = lotteryList.get(i)

if(cl.isContainKey(d)){

index = i

break

}

}

if(index == -1){

throw new IllegalArgumentException("概率集合设置不合理!")

}

return index

}

public double getMaxElement() {

return maxElement

}

public List<ContinuousList> getLotteryList() {

return lotteryList

}

public void setLotteryList(List<ContinuousList> lotteryList) {

this.lotteryList = lotteryList

}

}

该工具类的基本思想是,将抽奖概率分布到数轴上,如现有三个抽奖概率10、20、30,将三者依次添加到概率集合中,则构造的数轴为:0~10范围内表示概率10,10~30范围内表示概率为20,30~60范围内表示概率为30,数轴上的长度对应着相应的概率。由这种处理方式可知,概率总和并不需要等于1。该工具类的成功与否在于Random.nextDouble()能否等概率地生成0~1之间的任意一个数。

对该抽奖工具进行测试,测试类如下:

[java] view plain copy

package com.lottery

import java.util.ArrayList

import java.util.HashMap

import java.util.List

import java.util.Map

import java.util.Map.Entry

class Result{

private int index

private int sumTime

private int time

private double probability

private double realProbability

public int getIndex() {

return index

}

public void setIndex(int index) {

this.index = index

}

public int getTime() {

return time

}

public void setTime(int time) {

this.time = time

}

public int getSumTime() {

return sumTime

}

public void setSumTime(int sumTime) {

this.sumTime = sumTime

}

public double getProbability() {

return probability

}

public double getRealProbability() {

return realProbability

}

public void setRealProbability(double realProbability) {

this.realProbability = realProbability

}

public Result(){

}

public Result(int index, int sumTime, int time, double realProbability) {

this.setIndex(index)

this.setTime(time)

this.setSumTime(sumTime)

this.setRealProbability(realProbability)

}

public String toString(){

return "索引值:" + index + ",抽奖总数:" + sumTime + ",抽中次数:" + time + ",概率:"

+ realProbability + ",实际概率:" + (double)time/sumTime

}

}

public class TestLottery {

static final int TIME = 100000

public static void iteratorMap(Map<Integer, Integer> map, List<Double> list){

for(Entry<Integer, Integer> entry : map.entrySet()){

int index = entry.getKey()

int time  = entry.getValue()

Result result = new Result(index, TIME, time, list.get(index))

System.out.println(result)

}

}

public static void main(String[] args) {

//构造概率集合

List<Double> list = new ArrayList<Double>()

list.add(20d)

list.add(80d)

list.add(50d)

list.add(30d)

LotteryUtil ll = new LotteryUtil(list)

double sumProbability = ll.getMaxElement()

Map<Integer, Integer> map = new HashMap<Integer, Integer>()

for(int i = 0 i < TIME i++){

int index = ll.randomColunmIndex()

if(map.containsKey(index)){

map.put(index, map.get(index) + 1)

}else{

map.put(index, 1)

}

}

for(int i = 0 i < list.size() i++){

double probability = list.get(i) / sumProbability

list.set(i, probability)

}

iteratorMap(map, list)

}

}

运行结果:

由结果可知,抽奖100000时, 得到的实际概率基本与正式概率相当。

以下说明此类调用方式:

[java] view plain copy

public LotteryUtil(List<Double> list)

说明:构造方法,传入参数为一个概率集合

[java] view plain copy

public int randomColunmIndex()

功能:进行抽奖 *** 作,返回List集合的索引下标,此下标对应的概率的奖品即为抽中的奖品

红包剩余金额为 M

红包剩余数量为 N

这种算法就是每次都在区间[0,M/N×2] 随机取一个数。假设100元红包发10个人,那么合理的做法应该是每个人领到10元的概率相同。

这样推导下去,每个人领到相同金额的概率应该就是相同的了。

第一次生成随机数: k1=(0,sum/n*2) (左开右开区间内的随机数)

第二次生成随机数:k2 = (0,(sum-k1)/(n-1)*2)

第三次生成随机数:k3 = (0,(sum-k1-k2)/(n-2)*2)

第N次生成随机数:kn = sum-k1-...-kn-1

这个算法可以把总金额想象成一条线段,每个人都有机会切一刀,前面的人切剩下的后面的人再接着切,这样越是前面的人截取的长度(理解成领取到的红包金额)越大的概率就越大。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11727318.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-18
下一篇 2023-05-18

发表评论

登录后才能评论

评论列表(0条)

保存