【问题标题】:java random number generator - lotteryjava随机数生成器 - 彩票
【发布时间】:2012-04-16 07:05:25
【问题描述】:

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

我创建了一个彩票号码生成器,并注意到了奇怪但一致的结果。我的程序试图匹配之前的欧洲百万彩票开奖号码。我跟踪尝试的次数,并跟踪我匹配 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,因此无法投票。所有答案都有帮助,包括 cmets。

感谢所有成员的建议,我改进了我的程序,不出所料地发现了我的代码中的一个错误。 @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 再次欣赏可能组合的计算。我在程序中使用了这个,发现赢得彩票所花费的时间超过了组合的总数。我很可能会产生重复的随机数。由此我可能会创建所有可能的组合并随机选择每个组合,直到程​​序找到匹配项。

【问题讨论】:

  • 我在这里看到的唯一令人惊讶的是,您匹配 6 个数字的可能性是匹配 5 个数字的两倍,而我希望您匹配更多数字的可能性比匹配更少数字的可能性低。
  • 你的问题到底是什么?你期待什么?
  • @Samuel_xL 我正在寻找一个解释,说明为什么在使用 java 随机库时我一直在同一范围内实现百分比。公平地说,我应该这么说,我猜会有很多因素会影响我的结果,但我不确定它们是什么。

标签: java random


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    你的意思是你希望你赢的次数比例更“随机”吗?如果这就是您的意思,那么@truthreality 是非常正确的。如需进一步阅读,您可以查看law of large numberscentral limit theorem

    如果您要问自己的洗牌方法是否正确,那是因为它效率低下。您生成的随机数超出了必要的数量,因为您只是在发生欺骗时检查它们,并且在您选择球后不会创建新的随机数,因此您至少需要一个 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;
    }
    

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

    【讨论】:

    • 感谢您的建议,我知道这可能会更有效,我查看了您建议的链接,真的很有帮助!
    【解决方案3】:

    据我了解,百万欧元有两个不同的部分。 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
    

    【讨论】:

    • 感谢唯一代的总数,我将使用这个数字进行检查,即如果我无法在 1.16 亿次尝试中产生获胜组合,则退出程序并返回总数匹配的彩票号码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-17
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    • 2015-12-06
    • 2023-03-11
    相关资源
    最近更新 更多