2012-04-11 100 views
0

我的代码看起来业余,因为我是第二年的软件工程学生。java随机数发生器 - 彩票

我创建了一个彩票号码发生器,并已注意到特殊但一致的结果。我的程序试图匹配以前的欧洲百万彩票抽奖号码。我跟踪它需要的尝试次数,并且还跟踪匹配3,4,5和6个数字的次数。

这些尝试的范围在100万到422百万之间。即我会运行程序10次,我会达到一个范围,我也会跟踪每次运行所花费的时间。

我考虑了很多事情,例如防止随机数被多次使用,并且此检查是针对可能的彩票号码的HashMap完成的。如果我在散列表中找到随机数字,我将数字添加到数组列表中,然后从散列表中删除数字。

我的问题围绕着结果。

在所有匹配彩票号码的尝试中,我获得3个号码的机会平均为3.13%。 4个数字下降到0.28%,5个数字0.00012%,6个数字0.00022%。

可以理解随着彩票数量增加,获胜的机会将会减少,但无论我有100万次还是1亿次尝试,这个比例是相同的还是非常接近的。

如果你有兴趣,我的最小尝试次数是1,088,157次,大约需要6秒或6612ms。

尝试次数最多的是422,036,905次,耗时26分钟或1589867ms。

因为我正在使用Java随机库,所以我只是在寻找一些清晰的内容。或者我应该简单地把它归结为概率?

我的代码是不必要的225行,如果您想查看某个特定部分或更愿意查看整个事情,请请求此操作。下面是前5个数字随机数生成的示例。

//stores all possible lottery numbers 
public static HashMap<Integer,Integer> randRange = new HashMap<Integer,Integer>(); 

//stores bonus ball numbers 
public static HashMap<Integer,Integer> boRange = new HashMap<Integer,Integer>(); 

//stores lottery number output 
public static ArrayList<Integer> lotNum = new ArrayList<Integer>(); 

//stores bonus ball output 
public static ArrayList<Integer> boNum = new ArrayList<Integer>(); 

public static void randomInt(){ 

    Random rand = new Random(); 

    //generate a random number 
    int RandInt = rand.nextInt(51); 
    int boInt = rand.nextInt(12); 

    //loop used to get unique random number 
    int count=0; 
    while(count!=5){ 

     //check if random number exists 
     if(randRange.get(RandInt)!=null) 
     { 
      //finalise random number 
      RandInt=randRange.get(RandInt); 

      //add to ArrayList 
      lotNum.add(RandInt); 

      //remove number 
      //ensures next random number is unique 
      randRange.remove(RandInt); 

      count++;     
     } 

     else 
     { 
      //get a new random number 
      //and start process again 
      RandInt = rand.nextInt(51); 
     } 
    } 
} 

编辑:

所有遗憾,因为我有小于15声誉我不能给予好评的第一位。所有答案都有帮助,包括评论。

感谢所有成员的建议,我改进了我的程序,发现我的代码中出现了不可思议的错误。 @digitaljoel你是正确的匹配5和6号码的概率。我错误地设置了计算,例如欧洲联盟第三轮比赛的数据为11,20,30,35,45,2,3为0.7%,4为0.05%,5为0.00273%,6​​为0.00776%。

感谢@maybewecouldstealavan我改变了我的洗牌方法,简单地填充一个ArrayList和洗牌列表,得到前五个数字,并为奖金球做同样的事情。好处在于每秒支票数量从每秒150-200万支票增加到每秒250-700万支票。

感谢@trutheality在某些情况下,如果我检查1000或1,000,000匹配的变化是相似或分钟。

@LeviX再次欣赏可能组合的计算。我在程序中使用了这个功能,发现花费的彩票组合总数超过了总数。我最有可能产生重复的随机数字。从这我可能会创建所有可能的组合,并随机选择每个组合,直到程​​序找到匹配。

+3

我在这里看到的唯一惊喜是,你匹配6个数字的可能性是你匹配5个数字的两倍,而我希望你不太可能匹配更多的数字。 – digitaljoel 2012-04-11 21:51:25

+0

你的问题到底是什么?你期望什么? – KeatsPeeks 2012-04-11 22:10:34

+0

@Samuel_xL我正在寻找一个解释,为什么当使用java随机库,我保持在同一范围内的百分比。为了公平起见,我应该说明这一点,我猜想会有很多因素可能影响我的结果,但我不确定它们是什么。 – thirdOctet 2012-04-11 22:43:55

回答

0

你的意思是你期望的,你赢得更多的“随机”倍的比例?如果这就是你所得到的,那么@真实性是非常正确的。为了进一步阅读,你可以看看law of large numberscentral limit theorem

如果你问你的洗牌方法是否正确,它虽然效率低下。你生成的随机数超过了必要的数值,因为你只是在发生错误时检查它们,而且在你选择一个球之后你不会创建一个新的随机数,所以你至少需要一个HashMap.get (int)。

我可能会使用以下方法,而不是之一:

1)创建一个包含所有球值的ArrayList。对于每张图纸,使用Collections.shuffle(yourArrList, rand)来对它们进行克隆,然后使用列表中的前5个球。

2)再次,创建一个数组或球列表的ArrayList。然后自己实施一部分shuffle操作:从可能性的较小和较小子集中进行选择,并在不再适合刚刚选择的元素位置的元素中进行交换。好处是你不需要洗牌整个阵列。这里是我的快速和肮脏的实施:

public static int[] choose(int[] array, int count, Random rand) { 
    int[] ar = array.clone(); 
    int[] out = new int[count]; 
    int max = ar.length; 
    for (int i = 0; i<count; i++) { 
     int r = rand.nextInt(max); 
     //max is decremented, 
     //the selected value is copied out then overwritten 
     //by the last value, which would no longer be accessible 
     max--; 
     out[i]=ar[r]; 
     ar[r]=ar[max]; 
    } 
    return out; 
} 

很可能有改进的余地,特别是如果顺序并不重要。

+0

感谢您的建议,我知道它可以更有效率,我看着你的建议链接,真的很有帮助! – thirdOctet 2012-04-12 07:49:55

4

在所有匹配彩票号码的尝试中,我获得3个号码的机会平均为3.13%。 4个数字下降到0.28%,5个数字0.00012%,6个数字0.00022%。

可以理解随着彩票数量增加,获胜的机会将会减少,但无论我有100万次还是1亿次尝试,这个比例是相同的还是非常接近的。

这实际上并不令人意外。你最终在这里做的是估计正确猜测3,4,5或6个数字的概率。有更多的样本只会使你的估计值的变化更小,但即使是100万样本“尽可能少”,你的估计值也会接近确切的概率(你可以通过计算一些数学来计算)。

0

根据我的理解,欧洲百万富翁有两个不同的部分。 5个球,然后是2个奖金球。您可以通过确定获胜的确切概率来检查您的程序的数学。我相信你可以谷歌它,但它很容易计算。获得5个球总分50(顺序无关紧要)得到2个球的11(顺序无关紧要)

P(B) 11!/2!(11-2)! = 55 

两个的

P(A) = 50!/5!(50-5)! = 2,118,760 

概率

概率事件是独立的,所以把它们放在一起。

P(A) * P(B) = P(A&B) 
2,118,760 * 55 = 116,531,800 

因此彩票中奖的机会是:

1 in 116,531,800 
+0

感谢独特世代的总数,我会用这个数字来实现一个检查,即如果我不能在1.16亿次尝试中产生中奖组合,那么打破程序并返回匹配的彩票号码总数。 – thirdOctet 2012-04-12 07:46:14