问题:
一副扑克牌,除去大小王后共52张牌,随机从中抽八张牌,问八张牌的和最有可能是多少?
分析:
这52张牌,其实就是数字 1 2 3 。。。13, 每个数字出现4次。随机抽出8个数,问组成的和最有可能是多少?
很快想到了2种方法:
1.根据 大数定理 ,多次模拟抽牌,求和,看和的分布情况
2.在所有的C(52,8)种情况中,求出所有89(12-100)种情况和的组合数
解法1:
首先生成一副扑克牌,放入list中,每次随机取出一张牌后,list remove该元素,代码如下:
1 package test; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 8 public class LargeNumbersTest { 9 10 public static int getSum() { 11 //生成一副扑克牌,放入list 12 List<Integer> list=new ArrayList<Integer>(); 13 for(int i=1;i<14;i++){ 14 list.add(i); 15 list.add(i); 16 list.add(i); 17 list.add(i); 18 } 19 20 int[] a=new int[8]; 21 for(int i=0;i<8;i++){ 22 int random=(int)(Math.random()*list.size()); 23 //随机取出一张牌,并在list集合中去除对应的数 24 a[i]=list.get(random); 25 list.remove(random); 26 } 27 int sum=0; 28 for(int i=0;i<a.length;i++){ 29 sum+=a[i]; 30 } 31 return sum; 32 } 33 public static void main(String[] args) { 34 Map<Integer,Integer> map=new HashMap<Integer, Integer>(); 35 //多次重复试验 36 for(int i=0;i<1000000;i++){ 37 int key=getSum(); 38 //试验结果存入map中,记录出现的次数 39 if(map.keySet().contains(key)){ 40 map.put(key, map.get(key)+1); 41 }else{ 42 map.put(key, 1); 43 } 44 } 45 //输出map集合,本来想写一个按值排序的方法,搜了一下,太麻烦,果断放弃,改用excel处理结果 46 for(Integer key:map.keySet()){ 47 System.out.println(map.get(key)+" "+key); 48 } 49 } 50 }
运行5次后,输出结果在excel中排序,如下:
可以看出,和是56的结果最多,大概39800,(只要三万九千八,求和结果带回家。。。),根据大数定理,估计和最可能的数是 56 ,概率约等于 0.0398,
但是,和为57、55出现的次数也比较接近 56 ,是不是概率相等呢?
我们求一下每种情况的准确概率(大数定理只能估算概率),请看解法2。
解法2:
模拟计算机抽牌的每一种情况,求出每一种情况下的和。
1.如果按照每张牌的点数分类的话,每次抽牌都要考虑这张牌的点数 在本次抽牌中 出现的次数,太麻烦,所以对每张牌进行编号(0-51),
问题转化为:在0-51中取出8个不同的数字,并对这8个数字代表的点数 求和。
2.8个数字,8个变量,8次循环,感觉很low啊,不过我没想到好的办法,就先这样吧,希望大家找到好的办法能分享给我。
代码如下:
1 package test; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 8 public class PokerTest { 9 public static void main(String[] args) { 10 //生成一副扑克牌,放入list 11 List<Integer> list=new ArrayList<Integer>(); 12 for(int i=1;i<14;i++){ 13 list.add(i); 14 list.add(i); 15 list.add(i); 16 list.add(i); 17 } 18 int count=0; 19 Map<Integer,Integer> map=new HashMap<Integer, Integer>(); 20 //模拟每一种抽牌结果,low到爆的8次循环 21 for(int a1=0;a1<45;a1++){ 22 for(int a2=a1+1;a2<46;a2++){ 23 for(int a3=a2+1;a3<47;a3++){ 24 for(int a4=a3+1;a4<48;a4++){ 25 for(int a5=a4+1;a5<49;a5++){ 26 for(int a6=a5+1;a6<50;a6++){ 27 for(int a7=a6+1;a7<51;a7++){ 28 for(int a8=a7+1;a8<52;a8++){ 29 int sum=list.get(a1)+list.get(a2) 30 +list.get(a3)+list.get(a4) 31 +list.get(a5)+list.get(a6) 32 +list.get(a7)+list.get(a8); 33 //记录抽牌总次数 34 count++; 35 //抽牌结果记录到map中,并记录次数 36 if(map.keySet().contains(sum)){ 37 map.put(sum, map.get(sum)+1); 38 }else{ 39 map.put(sum, 1); 40 } 41 } 42 } 43 } 44 } 45 } 46 } 47 } 48 } 49 for(Integer key:map.keySet()){ 50 System.out.println(map.get(key)+" "+key); 51 } 52 System.out.println("count===="+count); 53 } 54 55 }
结果依然是输出到excel中处理,
首先 count====752538150 。。。。。超乎想象的大,看来解法一中的循环次数还是太少。
用C(52,8)计算了下,这个结果没错
概率计算结果
得到和为 56 的概率为 0.039791 ,和解法1中估算的值 0.0398 比较接近了
和为55、57的概率同为 0.039601 ,与和为 56 的概率差距真的很小了,
就这样了