Генерация случайных типу uint

мне нужно генерировать случайные числа с диапазоном для byte, ushort, sbyte, short, int и uint. Я могу генерировать для всех этих типов, используя случайный метод в C# (например,values.Add((int)(random.Next(int.MinValue + 3, int.MaxValue - 2)));) за исключением uint с Random.Next принимает только значения int.

есть ли простой способ генерировать случайные uint?

4 ответов


самый простой подход, вероятно, будет использовать два вызова: один для 30 бит и один для двух последних. Более ранняя версия этого ответа предполагала, что Random.Next() у включительно верхний предел int.MaxValue, но оказывается, что это эксклюзивно, поэтому мы можем получить только 30 однородных бит.

uint thirtyBits = (uint) random.Next(1 << 30);
uint twoBits = (uint) random.Next(1 << 2);
uint fullRange = (thirtyBits << 2) | twoBits;

(вы можете взять его в двух 16-битных значениях, конечно, в качестве альтернативы... или различные варианты между ними.)

кроме того, вы можете использовать NextBytes для заполнения 4-байт массив, затем используйте BitConverter.ToUInt32.


дневные кубики Хосе

или есть простой способ генерировать истинный случайный uint?

я признаю, что это не OQ. Станет ясно, что существуют более быстрые способы генерации случайных uints, которые не являются истинными. Тем не менее я предполагаю, что никто не слишком заинтересован в их генерации, за исключением тех случаев, когда по какой-то причине требуется неплоское распределение. Давайте начнем с некоторых исследования чтобы сделать его легко и быстро в C#. Удобный и fast часто ведет себя как синонимы, когда я пишу код.

во-первых: некоторые важные свойства

посмотреть MSDN.

Random конструкторы:

  • Random(): инициализирует новый экземпляр Random class, используя зависящее от времени начальное значение по умолчанию.
  • Random(int seed): инициализирует новый экземпляр Random class, используя указанное начальное значение.

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

private static Random rand = new Random();

Random методы:

  • rand.Next(): возвращает положительное случайное число, большее или равное нулю, меньше!--18-->.
  • rand.Next(int max): возвращает положительное случайное число, большее или равное нулю, меньше max, max должно быть больше или равно нуль.
  • rand.Next(int min, int max): возвращает положительное случайное число, большее или равное min, меньше max, max должно быть больше или равно min.

домашнее задание показывает, что rand.Next() о как rand.Next(int max).

второе: решение.

предположим, что положительный int имеет только два бита, забудьте бит знака, это ноль,rand.Next() возвращает три различных значения с равной вероятностью:

00
01
10

для истинного случайного числа младший бит равен нулю, так часто, как, же на старший бит.
Чтобы заставить его работать для использования самого низкого бита:rand.Next(2)

предположим, что int имеет три бита, rand.Next() возвращает семь различных значений:

000
001
010
011
100
101
110

чтобы он работал для самых низких двух битов, используйте:rand.Next(4)

предположим, что int имеет n бит.
Чтобы заставить его работать на n биты использовать: rand.Next(1 << n)

сделать его работать для максимума 30 бит использовать: rand.Next(1 << 30)
Это максимум, 1 int.MaxValue.

что приводит к способу генерации истинного случайного uint:

private static uint rnd32()
{
    return (uint)(rand.Next(1 << 30)) << 2 | (uint)(rand.Next(1 << 2));
}

быстрая проверка: какова вероятность генерации нуля?

1 2, 1 30

шанс на ноль: 1/22 * 1/230 = 1/232 Общее количество кораблей, в том числе ноль: 232
Ясно как день, никакого смога, не так ли?

наконец: вводящая в заблуждение идея.

можно ли сделать это быстрее, используя rand.Next()

                            int.Maxvalue is:    (2^31)-1
   The largest value rand.Next() returns is:    (2^31)-2 
                           uint.MaxValue is:    (2^32)-1

, когда rand.Next() используется дважды, и результаты добавляются, максимально возможное значение:

2*((2^31)-2) = (2^32)-4 

разница с uint.MaxValue является:

(2^32)-1 - ((2^32)-4) = 3

до uint.MaxValue еще одна ценность, rand.Next(4) должно быть добавлено, таким образом мы получить:

Рэнд.Next () + rand.Next () + rand.Далее(4)

какова вероятность генерации нуля?

приблизительно: 1/231 * 1/231 * 1/4 = 1/264, оно должно быть 1/232

Подождите секунду, как насчет:

2 * rand.Next() + rand.Next(4)

опять же, какова вероятность генерации нуля?

приблизительно: 1/231 * 1/4 = 1/233, слишком мало, чтобы быть действительно случайным.

еще один простой пример:

rand.Next(2) + rand.Next(2), все возможные результаты:

       0 + 0 = 0
       0 + 1 = 1
       1 + 0 = 1
       1 + 1 = 2

равными вероятностями? Нет пути Хосе.

заключение: добавление истинных случайных чисел дает случайное число, но не истинное случайное число. Бросают две игральные кости ...


задайте диапазон, "uint u0

легче начать с диапазона от " нуля "(включительно) до" u " (включительно).
Ты мог бы взглянуть на мою другую. ответ. Если вас интересует более быстрый / эффективный способ:
равномерные псевдослучайные числа в диапазоне. (это довольно много кода/текста).

ниже" rnd32 (uint u) " возвращает: 0 Самый сложный случай: "u = int.Максвеллову". Тогда вероятность того, что первая итерация "do-loops"
(одна итерация как внешнего, так и внутреннего "do-loop"), возвращает допустимое значение 50%.
После двух итераций вероятность составляет 75% и т. д.

вероятность того, что внешний "do-loop" повторяется более одного раза, невелика.
В случае " u = int.Значением maxvalue": 0%.

очевидно, что: "rnd32 (uint u0, uint u1)" возвращает значение между ц0 (в т. ч.) и U1 (включительно).

private static Random rand = new Random();

private static uint rnd32(uint u)                                 //  0 <= x <= u
{
    uint x;
    if (u < int.MaxValue) return (uint)rand.Next((int)u + 1);
    do                                         
    {
        do x = (uint)rand.Next(1 << 30) << 2;
        while (x > u);
        x |= (uint)rand.Next(1 << 2);
    }
    while (x > u);
    return x;
}

private static uint rnd32(uint u0, uint u1)                      // set the range
{
    return u0 < u1 ? u0 + rnd32(u1 - u0) : u1 + rnd32(u0 - u1);
}

public uint NextUInt() 
{
    uint x=int.MinValue;
    uint y;
    uint z;
    uint w;
    uint t= (x^(x<<11)); 
    x=y;
    y=z; 
    z=w;
    return (w= (w^(w>>19))^(t^(t>>8)));
}

пожалуйста, попробуйте эту функцию.