2015-10-14 2 views
-1

Я хочу знать, если есть возможность выполнить следующую ситуацию:Динамически настраивать диапазон генераторов, исключая номера?

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

Random generator = new Random(0, 100); 

Если я печатаю generator.next(), я получаю номер 40 (например). Теперь, когда я снова набираю generator.next(), я хочу получить новое случайное число, в диапазоне (0 - 39, 41 - 100). Поэтому я хочу исключить сгенерированные числа из диапазона генератора.

Возможно ли это?

+2

Если ваша конечная цель - получить N случайных чисел от 0 до 100 без дубликатов, это не совсем так, как это сделать. – Jon

+4

Может быть намного проще создать список из 0-100, перетасовать список, а затем поместить первый элемент по одному. – ryanyuyu

+1

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

ответ

-2

Составьте список целых чисел

var myList = new List<int>(); 
var myrandom = new Random(); 

Когда вам нужно случайное, сделать это:

int newRandom; 
while(true){ 
    newRandom = myrandom.Next(0,100); 
    if (!myList.Contains(newRandom)){ 
     myList.Add(newRandom); 
     break; 
    } 
} 
//continue execution here 
System.Diagnostics.Debug.Print(newRandom); 
+0

Это будет работать, но не должно использоваться, если вы даже отдаленно обеспокоены эффективностью.Это зависит от удачи/шанса в конечном итоге вывести номер, которого у вас еще нет. – leigero

+0

A SortedList будет более эффективным. «Удача» ??? –

+0

@ IoniţăCosmin практически любое решение лучше, чем это, и их нетрудно найти. Вот кто-то, кто знает много объяснения: http://stackoverflow.com/questions/2351308/random-number-generator-in-c-sharp-unique-values/2351735#2351735 – Jon

0

Идея в коде ниже (не гарантируется компилировать ... это от вершины моей головы), состоит в том, чтобы составить список доступных номеров, затем случайным образом выбирать из этого списка, удаляя их по мере их выбора. Это позволяет избежать чрезмерной генерации случайных чисел. Вам нужно всего лишь генерировать 99 случайных чисел. Когда вы доберетесь до одного числа слева, вы просто добавите его в конец.

var countWanted = 100; 
var dest = new List<int>(countWanted); 
var source = new List<int>(); 
for (int i = 0; i < 100 ; i++) source.Add(i); 
var r = new Random(); 
for (int i = 100; i > 100-countWanted; i--) 
    var n = r.Next(0,i); 
    dest.Add(source[n]); 
    source[n] = source[i-1]; 
} 
+0

Заметим, что это алгоритм O (n^2) для решения этой задачи, тривиально разрешимый в O (n) времени. – Servy

+0

Согласовано. Но тривиальная разница с маленькими n. Я все равно это исправлю. – hatchet

1

Это позволило бы создать COUNT уникальных случайных чисел в диапазоне от 0 - 100

public IEnumerable<int> Randomize(int count, int seed) 
{ 
    var generator = new Random(seed); 

    return Enumerable.Range(0, 100) 
     .Select(x => new { Value = x, SortOrder = generator.Next() }) 
     .OrderBy(x => x.SortOrder) 
     .Select(x => x.Value) 
     .Take(count); 
} 
+0

Будет ли это работать в маловероятном, но возможном случае, когда генератор дает вам одно и то же значение более одного раза? – hatchet

+0

Конечно, это просто для заказа ... –

+1

@hatchet Это приводит к небольшому уклонению в результатах. 'OrderBy' использует стабильный сортировку, поэтому элемент ранее в последовательности появляется сначала как тай-брейк, если элемент сортировки тот же. Это означает, что если вы заказываете список из 2 предметов, первый элемент имеет 1/(2^32) больше шансов быть первым элементом в результате. Для некоторых людей это довольно небольшое несоответствие от четного типа, чтобы игнорировать, но вполне возможно, что для некоторых приложений это неважное отклонение от истинного равномерного распределения. – Servy

0

Вам даже не нужно Random объект:

var uniqueRandomNums = Enumerable.Range(0, 100) 
         .OrderBy(n => Guid.NewGuid()) 
         .Take(num) 
         .ToList(); 
+0

Правда, не думал об этом, умный. –

+1

GUID не являются случайными. – Servy

+0

@ w.b Но GUIDS даже не предназначены для * приблизительной * случайности. «Случайный» близок к приблизительной истинной случайности, насколько это возможно. GUID полностью могут возвращать значения, которые всегда являются последовательными (и фактически будут делать именно это с использованием определенных алгоритмов генерации GUID), что приведет к тому, что этот код всегда будет возвращать исходный набор. – Servy

0

А Класс, как это будет это хорошо:

using System; 
using System.Collections.Generic; 

namespace RandomTools 
{ 
    public class NonRepeatingRandom 
    { 
     private Random _random; 
     private List<int> _possibleValues; 

     public NonRepeatingRandom(int minValue, int maxValue) 
     { 
      _random = new Random(); 
      _possibleValues = new List<int>(); 

      for (var i = minValue; i < maxValue; i++) 
      { 
       _possibleValues.Add(i); 
      } 
     } 

     public int Next() 
     { 
      var possibleValuesCount = _possibleValues.Count; 
      if (possibleValuesCount == 0) 
      { 
       return -1; 
      } 

      var nextIndex = _random.Next(0, possibleValuesCount); 
      var nextValue = _possibleValues[nextIndex]; 
      _possibleValues.RemoveAt(nextIndex); 

      return nextValue; 
     } 
    } 
} 

И вы можете просто использовать его как это:

using RandomTools; 

....

var myRandom = new NonRepeatingRandom(0, 100); 
var nextValue = myRandom.Next(); 

Когда вы исчерпали все возможные значения, то возвращается -1.

+0

Заметим, что это алгоритм O (n^2) для решения этой задачи, тривиально разрешимый в O (n) времени. – Servy

+0

@Servy Где n^2? Он прокручивает количество элементов один раз для генерации одного из каждого числа - это * n *. Затем он обслуживает их по одному за раз, что также * n *. O (2n) - O (n). – ErikE

+0

@ErikE Генерация каждого номера в вашем примере является операцией O (n), поскольку вы удаляете элемент из «списка»., И вы выполняете эту операцию O (n) n раз, что является O (n^2). – Servy

Смежные вопросы