0

我的代码看起来很业余,因为我是二年级的软件工程专业学生。

我创建了一个彩票号码生成器,并注意到了奇特但一致的结果。我的程序试图匹配之前的欧洲百万彩票开奖号码。我跟踪它所花费的尝试次数,我还跟踪我匹配 3、4、5 和 6 个数字的次数。

尝试的范围在 100 万到 4.22 亿之间。即我会运行程序 10 次,我会达到一个范围,我还会跟踪每次运行所花费的时间长度。

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

我的问题围绕着结果。

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

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

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

最大尝试次数为 422,036,905 次,耗时 26 分钟或 1589867 毫秒。

由于我使用的是 Java Random 库,因此我只是想弄清楚这一点。还是我应该简单地将其归结为概率?

我的代码是不必要的 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 匹配 3 是 0.7%,4 是 0.05%,5 是 0.00273%,6 是 0.000076 %。

感谢@maybewecouldstealavan,我改变了我的洗牌方法,简单地填充一个 ArrayList 并洗牌列表,获取前五个数字并对奖金球做同样的事情。好处是每秒检查的数量从每秒 150-20 万次检查增加到每秒 250-70 万次检查。

感谢@trutheality,因为在某些情况下,如果我检查了 1000 或 1,000,000 个匹配项,则变化是相似的或微小的。

@LeviX 再次感谢可能组合的计算。我在程序中使用了这个,发现赢得彩票所花费的时间超过了组合的总数。我很可能会产生重复的随机数。由此我可能会创建所有可能的组合并随机选择每个组合,直到程​​序找到匹配项。

4

3 回答 3

4

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

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

这实际上一点也不奇怪。你最终在这里做的是估计正确猜测 3、4、5 或 6 个数字的概率。拥有更多样本只会使您的估计值的变化更小,但即使“少”为 100 万个样本,您的估计值也应该接近确切的概率(您可以通过做一些数学计算)。

于 2012-04-11T21:47:00.573 回答
0

据我了解,百万欧元有两个不同的部分。5 个球,然后是 2 个奖金球。您可以通过计算获胜的确切概率来检查程序的数学运算。我相信你可以谷歌它,但它很容易计算。

从 50 个球中得到 5 个球的概率(顺序无关紧要)

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

从 11 个球中得到 2 个球的概率(顺序无关紧要)

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

这两个事件是独立的,所以将它们相乘。

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

因此,中奖的机会为:

1 in 116,531,800
于 2012-04-11T22:15:18.290 回答
0

你的意思是你期望你赢得的次数比例更“随机”吗?如果这就是您的意思,那么@truthreality 是非常正确的。为了进一步阅读,您可以查看大数定律中心极限定理

如果你问你的洗牌方法是否正确,那是因为它效率低下。您生成的随机数超出了必要的数量,因为您只是在发生欺骗时检查它们,并且在您选择球后不会创建新的随机数,因此您至少需要一个 HashMap.get (int)每个选择。

我可能会改用以下方法之一:

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

2) 同样,创建一个球值的 Array 或 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;
}

可能还有改进的余地,尤其是在顺序无关紧要的情况下。

于 2012-04-11T23:36:39.667 回答