Вероятность случайных чисел - PullRequest
5 голосов
/ 10 сентября 2010

Я пытаюсь случайным образом выбрать, например, 4 числа.Мне нужно сравнить вероятность этих двух алгоритмов.

1 #

                int a = random.Next(0, 4);

                if (a = 0)
                    statement1
                if (a = 1) 
                    statement2
                if (a = 2)
                    statement3
                if (a = 3) 
                    statement4

2 #

                int a = random.Next(0, 1000)

                if (a < 250)
                    statement1
                if (a >= 250 && a < 500) 
                    statement2
                if (a >= 500 && a < 750)
                    statement3
                if (a >= 750) 
                    statement4

Прав ли я, если думаю, что это то же самое?Вероятность оператора1 в первом коде равна 1/4, а во втором коде - 250/1000, поэтому она также равна 1/4.Но кто-то сказал мне, когда я использую больший диапазон случайных чисел, как в коде 2 #, это статистически более точно.Я сделал проект, который многократно повторяет эти коды, но я не уверен, что он показывает мне некоторые результаты.

Ответы [ 4 ]

3 голосов
/ 10 сентября 2010

Они в точности эквивалентны (за исключением того факта, что первый не будет компилироваться из-за использования = вместо == в выражениях if).

Чтобы доказать это, посмотрите нареализация Random.Next(int, int).С вашими значениями Random.Next(0, 4) равно

(int) (Random.Sample() * 4)

и

Random.Next(0, 1000) равно

(int) (Random.Sample() * 1000)

, где Random.Sample() - это закрытый метод, который возвращает случайныйdouble.

Теперь должно быть легко увидеть, что Random.Next(0, 4) вернет 0 точно , когда Random.Next(0, 1000) вернет число от 0 до 250.

2 голосов
/ 10 сентября 2010

Псевдослучайные числа должны быть равномерно распределены независимо от диапазона.Если во втором примере, если вы просто выберете последние 4 бита (a & 3), вы получите такое же распределение, как если бы вы выбрали следующие 4 с (a>>2) & 3.То есть то, что вы алгоритмически делаете во втором примере с использованием диапазонов, это отбрасывание большого количества информации, которую дал вам генератор случайных чисел.Вы не получаете больше «случайности» с большим диапазоном.

Сказав это, псевдослучайные генераторы имеют свои особенности, но если вы не серьезно относитесь к этому, не стоит беспокоиться!

0 голосов
/ 10 сентября 2010

Мои тесты следующие

Из 10К-петли 2 были проведены тесты с диапазоном 1-4 и диапазоном 1-1000, вот результаты

1-4

  1 > 2484 times
  2 > 2519 times
  3 > 2511 times
  4 > 2487 times

0 - 1000

  1 - 250    > 2421 times
  250 - 500  > 2531 times
  500 - 750  > 2529 times
  750 - 1000 > 2490 times

Я пришел к выводу, что они не имеют значения, что когда-либо, вы должны войти в матрицы и так далее, чтобы иметь некоторый контроль над генерацией случайных чисел и так далее.

Примечание: мои тесты были выполнены на PHP, а исходный код приведен ниже.


<?php

$first = array(1=>0,2=>0,3=>0,4=>0);
$second = array('0 - 250' => 0, '250 - 500' => 0, '500 - 750' => 0,'750 - 1000' => 0);

for($i=0;$i<=10000;$i++)  //10K
{
    //First
    $f_number = rand(1,4);
    switch($f_number)
    {
        case 1: $first[$f_number]++; break;
        case 2: $first[$f_number]++; break;
        case 3: $first[$f_number]++; break;
        case 4: $first[$f_number]++; break;
    }

    //Second
    $s_number = rand(1,1000);
    if($s_number < 250) $second['0 - 250']++;
    if($s_number > 250 && $s_number < 500) $second['250 - 500']++;
    if($s_number > 500 && $s_number < 750) $second['500 - 750']++;
    if($s_number > 750) $second['750 - 1000']++;
}

var_dump($first,$second);
?>
0 голосов
/ 10 сентября 2010

Распределение равномерное, и его легко проверить:

public class Program
{
    static void Main(string[] args)
    {
        var random = new Random();
        const int iterations = 10000000;

        var hits1 = 1.0 * Enumerable.Range(1, iterations)
                                     .Select(i => random.Next(0, 4))
                                     .Where(i => i == 0).Count();
        Console.WriteLine(hits1 / iterations);

        var hits2 = 1.0 * Enumerable.Range(1, iterations)
                                     .Select(i => random.Next(0, 1000))
                                     .Where(i => i < 250)
                                     .Count();
        Console.WriteLine(hits2 / iterations);
    }
}
...