Генерация случайных типу 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)));
}
пожалуйста, попробуйте эту функцию.