不独立事件的条件概率选取——[即时]抽取【JAVA SE】

在写抽奖程序的时候碰到的一个问题:

1.在不预知组内成员的情况下(也不将数个中奖位置预读在内存中)保证每m个元素中总能抽中n个;

2.保证同等价值的元素抽取概率君相等为n‘/m;

3.n可分为n1,n2……;

 

选取的算法放弃经典概率的随机数生成,而改用条件概率;

1.首先判断第b/m位置的元素是否是a/n选取的特殊元素;P=(n-a)/(m-b+1);

2.进一步在a/n的基础上判断c/n’是否特殊;P=(n‘-c)/(n-a+1);

3.将2迭代在1的结果中判断;

4.若n'还可再分,重复2步骤;

 

实例代码如下

package full.hit;

public class fullhit {
 public static int geted = 0;
 public static boolean task = false;
 public static int[] a = new int[21];
 public static int[] b = new int[21];
 public static int[] c = new int[21];

 boolean first_hit(int round) {
  boolean tempmark;
  tempmark = false;
  int rate = 0;
  int fate = 0;
  rate = (int) ((4 - geted) * 10000 / (20 - round + 1));
  fate = (int) (10000 * Math.random() + 1);
  if (fate <= rate) {
   tempmark = true;
   geted++;
  }
  return tempmark;
 }

 int socend_hit() {
  int r;
  int f;
  int tempint = 0;
  r = (int) 10000 / (4 - geted + 1);
  f = (int) (10000 * Math.random());
  if ((task == false) & (f <= r)) {
   tempint = 1;
   task = true;
  } else {
   tempint = 0;
  }
  return tempint;
 }

 public static void main(String[] args) {
  int round = 0;
  int s = 0;// 模拟楼层计数器
  int ta = 0;// 一等奖检测
  int tb = 0;// 二等奖检测
  boolean mark;// 检测:不符合每20个出现1个一等奖和3个二等奖就终止程序
  fullhit fh = new fullhit();
  for (int i = 1; i <= 10000000; i++) {// 模拟10mX20个楼层
   round = 0;
   geted = 0;
   task = false;
   ta = 0;
   tb = 0;
   mark = true;
   while (round < 20) {
    round++;
    if (fh.first_hit(round)) {
     if (fh.socend_hit() == 1) {
      // 模拟一等奖;
      a[round]++;
      ta++;

     //省略处理一等奖的方法;
     } else {
      // 模拟二等奖;
      b[round]++;
      tb++;

     //同上
     }
    } else {
     // 模拟三等奖;
     c[round]++;

    同上
    }
   }
   if (ta != 1) {
    mark = false;
   }
   if (tb != 3) {
    mark = false;
   }
   if (mark == false) {
    System.out.println("error");
    break;
   }

  }
  for (int i = 1; i <= 20; i++) {
   // 查看选中概率
   System.out.print("a" + i + "的个数=" + a[i] + "(" + a[i] / 10000
     + "%。)|");
   System.out.print("b" + i + "的个数=" + b[i] + "(" + b[i] / 10000
     + "%。)|");
   System.out.print("c" + i + "的个数=" + c[i] + "(" + c[i] / 10000
     + "%。)");
   System.out.println("|");
   s = a[i] + b[i] + c[i];
  }
  System.out.println(s);
 }
}



 

 运行结果

a1的个数=499824(49%。)|b1的个数=1497290(149%。)|c1的个数=8002886(800%。)|
a2的个数=500605(50%。)|b2的个数=1498930(149%。)|c2的个数=8000465(800%。)|
a3的个数=500648(50%。)|b3的个数=1498506(149%。)|c3的个数=8000846(800%。)|
a4的个数=498906(49%。)|b4的个数=1499513(149%。)|c4的个数=8001581(800%。)|
a5的个数=499420(49%。)|b5的个数=1501569(150%。)|c5的个数=7999011(799%。)|
a6的个数=499057(49%。)|b6的个数=1499303(149%。)|c6的个数=8001640(800%。)|
a7的个数=499637(49%。)|b7的个数=1500461(150%。)|c7的个数=7999902(799%。)|
a8的个数=499751(49%。)|b8的个数=1497757(149%。)|c8的个数=8002492(800%。)|
a9的个数=499362(49%。)|b9的个数=1500223(150%。)|c9的个数=8000415(800%。)|
a10的个数=500398(50%。)|b10的个数=1501744(150%。)|c10的个数=7997858(799%。)|
a11的个数=500780(50%。)|b11的个数=1499652(149%。)|c11的个数=7999568(799%。)|
a12的个数=501419(50%。)|b12的个数=1500825(150%。)|c12的个数=7997756(799%。)|
a13的个数=499531(49%。)|b13的个数=1498670(149%。)|c13的个数=8001799(800%。)|
a14的个数=500125(50%。)|b14的个数=1499623(149%。)|c14的个数=8000252(800%。)|
a15的个数=499369(49%。)|b15的个数=1500529(150%。)|c15的个数=8000102(800%。)|
a16的个数=500528(50%。)|b16的个数=1499332(149%。)|c16的个数=8000140(800%。)|
a17的个数=500256(50%。)|b17的个数=1501182(150%。)|c17的个数=7998562(799%。)|
a18的个数=500026(50%。)|b18的个数=1500794(150%。)|c18的个数=7999180(799%。)|
a19的个数=500726(50%。)|b19的个数=1501076(150%。)|c19的个数=7998198(799%。)|
a20的个数=499632(49%。)|b20的个数=1503021(150%。)|c20的个数=7997347(799%。)|
10000000

可以看到a的概率在5%,b的概率在15%,c的概率在80%;同时mark没有因为每组中产生特殊元素不够而break;选取方式为单次产生随机,每次结果直接利用后消灭内存;符合开始的设定!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值