如何确保随机数生成的概率相等?

时间:2013-11-16 17:17:39

标签: java random

   Random r1 = new Random();

    for(int i=0; i<10; i++){
        System.out.print(r1.nextInt(10) + " ");
    }

一次运行的输出: 9 7 6 8 3 5 3 3 0 4

为什么不能以相同的概率生成0-9? 3单独发生三次,但1&amp;零次。

4 个答案:

答案 0 :(得分:5)

经验概率与理论概率不同。你看到的是,在这个的情况下,你有3个3而没有2个。如果你再次运行它,你会得到一个不同的集合。随着运行次数的增加,您将接近理论概率。

正如其他人所提到的那样,两次投掷硬币并且两次得到头部都表明硬币存在缺陷或头部有可能是荒谬的?不,如果你把它扔了几百万次并得到所有的头?那就更有可能了。

答案 1 :(得分:2)

如果你想随机化元素的顺序(0-9),你可能会寻找像Fisher-Yates Shuffle这样的东西。

例如:

Random random = new Random();
int[] values = {1, 2, 3, 4, 5};
for(int i = values.length; i > 0; i--) {
    int index = random.nextInt(i);
    int i1 = values[index];
    int i2 = values[i - 1];

    values[i - 1] = i1;
    values[index] = i2;
}

答案 2 :(得分:0)

似乎你不想要随机数字,而是一个洗牌的数字列表(就像一副52张牌)。

List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
Collections.shuffle(list);
// now display them. They will appear in random order, each exactly once
for (Integer i : list) {
    System.out.println(i);
}

答案 3 :(得分:0)

从OP的评论来看,要求变得更加清晰:

  

我想拆分多行文件。分配比率是   实例4:5。对于100行,40个转到一个文件,50个转到另一个文件   文件。拆分必须是随机的

因此不需要随机数,所需要的是数字1numLines的随机顺序。

这将满足要求:

public List<Integer> randomLines(final int numLines) {
    final List<Integer> lineNumbers = new ArrayList<>(100);
    //put the line numbers into the List
    //each line occurs exactly once
    for (int i = 1; i <= numLines; ++i) {
        lineNumbers.add(i);
    }
    final Random random = new Random();
    //Carry out a random reording of the List
    Collections.shuffle(lineNumbers, random);
    return lineNumbers;
}

为了测试这段代码,我创建了一个简单的测试用例:

  1. 选择随机分割点
  2. 为每个文件的行号创建两个Set<Integer.
  3. 确认Set的尺寸为splitPointnumLines - splitPoint
  4. 这是有效的,因为Set只能包含唯一的项目,所以如果有重复项,那么Set的大小就会错误:

    @Test
    public void testRandomLines() {
        final App app = new App();
        final List<Integer> lineNumbers = app.randomLines(100);
        //pick a random split point
        final int splitPoint = random.nextInt(lineNumbers.size());
        System.out.println(splitPoint);
        final Set<Integer> firstFile = new LinkedHashSet<>();
        final Set<Integer> secondFile = new LinkedHashSet<>();
        for (int i = 0; i < lineNumbers.size(); ++i) {
            if (i < splitPoint) {
                firstFile.add(lineNumbers.get(i));
            } else {
                secondFile.add(lineNumbers.get(i));
            }
        }
        assertThat(firstFile.size(), is(splitPoint));
        assertThat(secondFile.size(), is(lineNumbers.size() - splitPoint));
    }
    

    我希望这能回答你的问题。