java控制不同阶段中奖率的问题?

时间:2022-12-06 09:07:17
中奖概率是这样的,我们可能有几万条的数据,要求每20条数据中,18金币,8金币,1金币的中出概率分别为1/20,3/30,16/20.
意思就是我的总数据不确定,但每20个用户中有一个1等奖,三个2等奖,16个三个等,都是中奖的,多谢各位大神帮忙了

9 个解决方案

#1


需求不明确啊

是  一等奖中奖几率是    1/20  

还是  20个人 必然有一个一等奖

#2


多简单的数学问题啊。。。

#3


60个人一组,先随机出3个一等奖,边随机边从60中移除,避免重复,再随机出6个2等奖,从57中移除(同上),再随机出3个不中奖的,从51中移除(同上),剩下这48个中3等奖。

#4


确定是概率不是频率啊!
随机数0-19;小于1的一等,1-4的二等,4-19的三等。

#5


拙见,用集合的shuffle方法,楼主可以试试。


public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
int cnt = 45314;//假设有这么多人
for (int i = 0; i < cnt; i++) {
list.add(i);//当然这里也可以存每个用户的ID
}
Collections.shuffle(list);
List<Integer> fst = list.subList(0, cnt/20);//一等奖二十分之一
List<Integer> scd = list.subList(cnt/20, (cnt/20)+(cnt/20)*3);//二等奖二十分之三
List<Integer> thd = list.subList((cnt/20)+(cnt/20)*3,cnt);//剩下的都是三等奖
}

#6


应该是excel文件,对数据进行分页显示,20个一页;每页对象中随机一个id 金币+=18;随机另外两个没中过奖的id 金币+=8;其他的 金币+=1;然后对页进行循环,直到结束~

#7


你这个问题相当于预读一组20个回复,然后random一个1到20的数为一等奖,剩下19个数里random三个数为二等奖,其余为三等奖。等到这20个回复满了再重新预读一组。另一个思路是采用伪随机,逐步增加几率。比如一等奖从5%还是,那么第二次的几率就是5%/95%,第三次就是5%/90%依次类推,最后一个为100%。当出现中的情况修改概率为0。这样伪随机的概率能保证大样本整体概率为5%同时对每一个用户几率相对公平。不出现连续多个中奖和连续多个不中奖的情况。但是对于知道结果的用户来说容易察觉规律,通过小号刷帖提高自己中奖的规律。

#8



package choujiang;

public class hit {
    public static int a[]=new int[21];
    private int fate; 
private int rate;
   static boolean mark=false;//记录是否发出一等奖
   boolean go_hit(int round){//伪随机方法
   rate=(int)(100/(20-round+1));
   fate=(int)(100*Math.random());
   if (fate<rate){
   mark=true;
   }
return mark;
   }
   public static void main(String[] args){
   int round=0;
   for (int i=0;i<1000000;i++){//模拟10000000次
   hit see=new hit();
   round=1;
   mark=false;
   while (round<=20){
   if ((see.go_hit(round))==false){
   round++;
   }else{
   a[round]=a[round]+1;//累计结果观察概率
   System.out.println(round);//模拟抽奖中奖过程
   break;
   }
   }
       }
   for(int i=0;i<a.length;i++){
   System.out.println("a"+i+"is"+a[i]);//查看概率
   }
   }
}

运行结果
a1is50119
a2is47578
a3is44862
a4is42797
a5is48756
a6is45944
a7is50613
a8is46737
a9is49679
a10is51650
a11is52227
a12is51617
a13is50042
a14is51440
a15is50608
a16is53694
a17is52624
a18is52321
a19is53343
a20is53349
可以看出概率还是在5%左右的

#9


如果觉得精度不够的话可以把
rate=(int)(100/(20-round+1));       
 fate=(int)(100*Math.random()); 
改成
rate=(int)(10000/(20-round+1));       
 fate=(int)(10000*Math.random()); 
这样抽奖的结果
a1is50.0%   50326
a2is49.0%   49421
a3is49.0%   49928
a4is50.0%   50154
a5is49.0%   49835
a6is49.0%   49997
a7is49.0%   49611
a8is49.0%   49693
a9is49.0%   49898
a10is50.0%   50212
a11is50.0%   50006
a12is49.0%   49755
a13is49.0%   49729
a14is49.0%   49964
a15is50.0%   50793
a16is50.0%   50228
a17is50.0%   50056
a18is50.0%   50177
a19is49.0%   49940
a20is50.0%   50277

#1


需求不明确啊

是  一等奖中奖几率是    1/20  

还是  20个人 必然有一个一等奖

#2


多简单的数学问题啊。。。

#3


60个人一组,先随机出3个一等奖,边随机边从60中移除,避免重复,再随机出6个2等奖,从57中移除(同上),再随机出3个不中奖的,从51中移除(同上),剩下这48个中3等奖。

#4


确定是概率不是频率啊!
随机数0-19;小于1的一等,1-4的二等,4-19的三等。

#5


拙见,用集合的shuffle方法,楼主可以试试。


public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
int cnt = 45314;//假设有这么多人
for (int i = 0; i < cnt; i++) {
list.add(i);//当然这里也可以存每个用户的ID
}
Collections.shuffle(list);
List<Integer> fst = list.subList(0, cnt/20);//一等奖二十分之一
List<Integer> scd = list.subList(cnt/20, (cnt/20)+(cnt/20)*3);//二等奖二十分之三
List<Integer> thd = list.subList((cnt/20)+(cnt/20)*3,cnt);//剩下的都是三等奖
}

#6


应该是excel文件,对数据进行分页显示,20个一页;每页对象中随机一个id 金币+=18;随机另外两个没中过奖的id 金币+=8;其他的 金币+=1;然后对页进行循环,直到结束~

#7


你这个问题相当于预读一组20个回复,然后random一个1到20的数为一等奖,剩下19个数里random三个数为二等奖,其余为三等奖。等到这20个回复满了再重新预读一组。另一个思路是采用伪随机,逐步增加几率。比如一等奖从5%还是,那么第二次的几率就是5%/95%,第三次就是5%/90%依次类推,最后一个为100%。当出现中的情况修改概率为0。这样伪随机的概率能保证大样本整体概率为5%同时对每一个用户几率相对公平。不出现连续多个中奖和连续多个不中奖的情况。但是对于知道结果的用户来说容易察觉规律,通过小号刷帖提高自己中奖的规律。

#8



package choujiang;

public class hit {
    public static int a[]=new int[21];
    private int fate; 
private int rate;
   static boolean mark=false;//记录是否发出一等奖
   boolean go_hit(int round){//伪随机方法
   rate=(int)(100/(20-round+1));
   fate=(int)(100*Math.random());
   if (fate<rate){
   mark=true;
   }
return mark;
   }
   public static void main(String[] args){
   int round=0;
   for (int i=0;i<1000000;i++){//模拟10000000次
   hit see=new hit();
   round=1;
   mark=false;
   while (round<=20){
   if ((see.go_hit(round))==false){
   round++;
   }else{
   a[round]=a[round]+1;//累计结果观察概率
   System.out.println(round);//模拟抽奖中奖过程
   break;
   }
   }
       }
   for(int i=0;i<a.length;i++){
   System.out.println("a"+i+"is"+a[i]);//查看概率
   }
   }
}

运行结果
a1is50119
a2is47578
a3is44862
a4is42797
a5is48756
a6is45944
a7is50613
a8is46737
a9is49679
a10is51650
a11is52227
a12is51617
a13is50042
a14is51440
a15is50608
a16is53694
a17is52624
a18is52321
a19is53343
a20is53349
可以看出概率还是在5%左右的

#9


如果觉得精度不够的话可以把
rate=(int)(100/(20-round+1));       
 fate=(int)(100*Math.random()); 
改成
rate=(int)(10000/(20-round+1));       
 fate=(int)(10000*Math.random()); 
这样抽奖的结果
a1is50.0%   50326
a2is49.0%   49421
a3is49.0%   49928
a4is50.0%   50154
a5is49.0%   49835
a6is49.0%   49997
a7is49.0%   49611
a8is49.0%   49693
a9is49.0%   49898
a10is50.0%   50212
a11is50.0%   50006
a12is49.0%   49755
a13is49.0%   49729
a14is49.0%   49964
a15is50.0%   50793
a16is50.0%   50228
a17is50.0%   50056
a18is50.0%   50177
a19is49.0%   49940
a20is50.0%   50277