Обеспечьте равномерное (ish) распределение с генерацией случайных чисел

У меня есть список объектов, и я хотел бы постоянно получать к ним доступ в произвольном порядке.

Мне было интересно, есть ли способ гарантировать, что случайное значение не всегда было одинаковым.

Пример.

Мой список представляет собой список очередей, и я пытаюсь чередовать значения, чтобы создать реальный сценарий для тестирования.

Я не особо хочу, чтобы все элементы в очередях 1 и 2 располагались перед любым другим элементом. Есть ли гарантированный способ сделать это?

Спасибо

РЕДАКТИРОВАТЬ :: Список очередей, который у меня есть, в основном представляет собой список файлов, которые я передаю в веб-службу. Файлы должны быть в определенном порядке, следовательно, очереди.

Итак, у меня есть Queue1 = "set1_1.xml", set1_2.xml ", ..." set1_n.xml "Queue2 ... ... QueueN

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

На данный момент я просто использую простой рандом от 0 до (количество очередей), чтобы определить, какой файл удалить из очереди следующим. Это работает, но я спрашивал, можно ли было отказаться, чтобы получить больше единообразия, вместо того, чтобы иметь 50 файлов из Очереди 1 и 2, а затем 5 файлов из Очереди 3.

Однако я понимаю, что изменение случайности больше не делает ее случайной.

Спасибо за все ваши ответы.


person Rocco    schedule 06.02.2009    source источник
comment
Почему вы получаете 50 файлов из очереди 1 и 2, а затем 5 файлов из очереди 3? Если очереди выбираются случайным образом, вы должны получить примерно одинаковое распределение. Или я неправильно понимаю проблему?   -  person LukeH    schedule 06.02.2009
comment
они выбираются случайным образом. Но я обнаружил, что ранд на 1-3 не всегда очень случайный.   -  person Rocco    schedule 06.02.2009
comment
Можете ли вы опубликовать код, который вы используете для генерации случайных значений? Я получаю довольно хорошее распределение даже с небольшим набором значений.   -  person LukeH    schedule 06.02.2009


Ответы (4)


Что ж, не совсем понятно, каков сценарий, но случай со случайным никогда не скажешь ;-p. Все, что вы пытаетесь сделать, чтобы «гарантировать» тонкость, вероятно, уменьшит случайность.

Как ты это делаешь? Лично я бы сделал что-то вроде:

static IEnumerable<T> GetItems<T>(IEnumerable<Queue<T>> queues)
{
    int remaining = queues.Sum(q => q.Count);
    Random rand = new Random();
    while (remaining > 0)
    {
        int index = rand.Next(remaining);
        foreach (Queue<T> q in queues)
        {
            if (index < q.Count)
            {
                yield return q.Dequeue();
                remaining--;
                break;
            }
            else
            {
                index -= q.Count;
            }
        }
    }
}

Он должен быть достаточно равномерным по всему набору. Хитрость здесь в том, что, если рассматривать очереди как одну большую очередь, тенденция состоит в том, что очереди с большим количеством элементов будут удаляться из очереди быстрее (поскольку есть больше шансов получить индекс в их диапазоне). Это означает, что он должен автоматически балансировать потребление между очередями, чтобы все они работали без нагрузки (примерно) в одно и то же время. Если у вас нет LINQ, просто измените первую строку:

int remaining = 0;
foreach(Queue<T> q in queues) {remaining += q.Count;}

Пример использования:

static void Main()
{
    List<Queue<int>> queues = new List<Queue<int>> {
        Build(1,2,3,4,5), Build(6,7,8), Build(9,10,11,12,13)
    };
    foreach (int i in GetItems(queues))
    {
        Console.WriteLine(i);
    }
}
static Queue<T> Build<T>(params T[] items)
{
    Queue<T> queue = new Queue<T>();
    foreach (T item in items)
    {
        queue.Enqueue(item);
    }
    return queue;
}
person Marc Gravell    schedule 06.02.2009

Это зависит от того, чего вы действительно хотите ...

Если "случайные" значения действительно случайны, вы получите равномерное распределение с достаточным количеством итераций.

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

Итак, у вас может быть:

  • Действительно случайные значения с равномерным распределением, или
  • Контролируемое распределение, но уже не случайное
person LukeH    schedule 06.02.2009

Вы пытаетесь перемешать свой список?

Если да, вы можете сделать это, отсортировав его по случайному значению.

Попробуйте что-то вроде этого:

private Random random = new Random();
public int RandomSort(Queue q1, Queue q2)
{
  if (q1 == q2) { return 0; }
  return random.Next().CompareTo(random.Next());
}

А затем используйте RandomSort в качестве аргумента при вызове List.Sort ();

person Rune Grimstad    schedule 06.02.2009
comment
Использование Random таким образом очень ненадежно; в частности, он нарушает транзитивность и симметрию - person Marc Gravell; 06.02.2009
comment
(чтобы он работал, вам нужно будет сгенерировать и сохранить случайное значение для каждой записи, а затем отсортировать по этому значению - так, чтобы при тестировании {a, b} вы получили - {b, a } - person Marc Gravell; 06.02.2009
comment
Это правда, но если он просто хочет перебрать список в случайном порядке и убедиться, что он получает все элементы, он должен работать достаточно хорошо. - person Rune Grimstad; 06.02.2009

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

person Morten Christiansen    schedule 06.02.2009