非均匀随机化器

时间:2010-08-10 17:24:01

标签: java random hashmap

我需要从1到37生成6个唯一的随机数;起初我使用了一个简单的数组映射:

private int k=6, n=37;

public int[] Results ()
{
    // fill an array with numbers 1 2 3 . . . n
    int[] numbers = new int[n];
    for (int i = 0; i < numbers.length; i++)
        numbers[i] = i + 1;

    // draw k numbers and put them into a second array
    int result[] = new int[k];
    for (int i = 0; i < result.length; i++)
    {
        // make a random index between 0 and n - 1
        int r = (int) (Math.random() * n);
        // pick the element at the random location
        result[i] = numbers[r];
        // move the last element into the random location
        numbers[r] = numbers[n - 1];
        n--;
    }
    return result;
}

问题是在很多情况下我得到了近乎均匀的分布(特别是当我少于10次抽签时),即:1,9,16,18,24,30或5,16,18,22 ,26,29

我真正需要的是一个真正的随机数发生器,可以给我以下结果: 11,16,25,29,30,32或4,8,9,15,18,19在LESS然后10次抽签。

我还看到了类似的HashMap实现:

import java.util.*;

public class RandomHash
{
    HashMap numbers = new HashMap() ;
    Random rnd_gen = new Random() ;

    RandomHash()
    {
        for(;;)
        {
            int rnd_num = rnd_gen.nextInt() ;
            Integer rnd_num_obj = new Integer(rnd_num) ;

            if (! numbers.containsKey(rnd_num_obj) )
            {
                numbers.put(rnd_num_obj, rnd_num_obj) ;
                /* Do whatever with the number */
                break ;
            } /* else loop and get another rnadom num */

        } /*end for*/
    }
}

问题是我目前不知道如何将randomizer和hashmap分别绑定到6和32。 hashmap会给出更多混乱的结果吗?

5 个答案:

答案 0 :(得分:4)

你可以通过一个随机号码来完成! 10是九太多了: - )

请注意,您的6个号码正好有37种可能性。

所以,你需要做的就是选择1到2324784之间的随机数(37选择6)。

然后使用映射来获得6个元素的相应组合。有关映射的示例,请参阅此处:Generating the mth Lexicographical Element of a Mathematical Combination

MSDN代码的Java端口位于:http://the-lost-beauty.blogspot.com/2010/07/generating-combinations-in.html

答案 1 :(得分:3)

你要求随机数,这就是你得到的。你的两个例子:11,16,25,29,30,32和4,8,9,15,18,19比你认为均匀分布的结果更不可能。

让我们举例来看看你的最后一个结果,为简化说你希望所有数字都小于或等于19.如果你选择1到32之间的单个数字,你有19/32的机会(appr 59) %)为19或更少。如果您在1到32之间选择6个不同的数字,则所有这些数字的可能性不到3%为19或更低。

当你运行你的代码100次时,我实际上有五个列表符合要求,这比统计预期的要多两个:

[3,8,13,16,18,19]

[2,3,6,8,10,14]

[2,6,7,8,13,18]

[4,5,9,10,11,12]

[8,12,13,15,16,17]

答案 2 :(得分:2)

我只是将第一个数组洗牌(在初始化步骤之后)并取得前6个元素。你可以使用像

这样的东西
Collections.shuffle( Arrays.asList(array) );

使用该语言的内置函数对数组进行随机播放。

如果你从1,000,000个元素中选择它可能是一个性能问题,但只有37个我认为改组是一个更清晰的解决方案。

答案 3 :(得分:0)

线性同余发生器模37,具有适当选择的参数?

可替换地,

List l = Arrays.asList(numbers);
Collections.shuffle(l);
return l.subList(0,k).toArray();

请注意,它希望数字为Object []并返回另一个Object []。

答案 4 :(得分:0)

这是一个非均匀分布:

return new int[]{1,2,3,4,5,6};