Самый быстрый способ генерации случайного логического
Итак, существует несколько способов создания случайного bool в С#:
- Использование Random.Next():
rand.Next(2) == 0
- Использование Random.NextDouble():
rand.NextDouble() > 0.5
Есть ли разница? Если да, то какая из них на самом деле имеет лучшую производительность? Или есть другой способ, который я не видел, может быть еще быстрее?
Ответы
Ответ 1
Первый вариант - rand.Next(2)
выполняет за кадром следующий код:
if (maxValue < 0)
{
throw new ArgumentOutOfRangeException("maxValue",
Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", new object[] { "maxValue" }));
}
return (int) (this.Sample() * maxValue);
а для второго варианта - rand.NextDouble()
:
return this.Sample();
Поскольку первая опция содержит проверку, умножение и приведение maxValue
, вторая опция, вероятно, быстрее.
Ответ 2
Небольшое усиление для опции второй:
Согласно MSDN
public virtual double NextDouble()
возвращает
Число с плавающей запятой с двойной точностью, большее или равное 0,0, и менее 1,0.
Итак, если вы хотите равномерно распределить случайный bool, вы должны использовать >= 0.5
rand.NextDouble() >= 0.5
Диапазон 1: [0.0... 0.5 [
Диапазон 2: [0,5... 1,0 [
| Диапазон 1 | = | Диапазон 2 |
Ответ 3
Я провел тесты с секундомером. 100 000 итераций:
System.Random rnd = new System.Random();
if (rnd.Next(2) == 0)
trues++;
Процессоры любят целые числа, поэтому метод Next (2) был быстрее. 3700 против 7500 мс, что весьма существенно. Кроме того: я думаю, что случайные числа могут быть узким местом, я создал около 50 каждого кадра в Unity, даже с крошечной сценой, которая заметно замедляет мою систему, поэтому я также надеялся найти метод для создания случайного бул. Так я тоже попробовал
if (System.DateTime.Now.Millisecond % 2 == 0)
trues++;
но вызов статической функции был еще медленнее с 9600 мс. Стоит выстрел. Наконец, я пропустил сравнение и создал только 100 000 случайных значений, чтобы убедиться, что сравнение int и double не влияло на прошедшее время, но результат был почти таким же.
Ответ 4
Самый быстрый. Вызов метода Random.Next
имеет меньше накладных расходов. Приведенный ниже метод расширения работает на 20% быстрее, чем Random.NextDouble() > 0.5
, и на 35% быстрее, чем Random.Next(2) == 0
.
public static bool NextBoolean(this Random random)
{
return random.Next() > (Int32.MaxValue / 2);
// Next() returns an int in the range [0..Int32.MaxValue]
}
Быстрее, чем быстрее. Можно сгенерировать случайные логические значения с помощью класса Random
еще быстрее, используя приемы. 31 старших биты генерируемого int
могут быть использованы в течение 31 последующих логических производств. Реализация сильфона на 40% быстрее, чем ранее заявленная как самая быстрая.
public class RandomEx : Random
{
private uint _boolBits;
public RandomEx() : base() { }
public RandomEx(int seed) : base(seed) { }
public bool NextBoolean()
{
_boolBits >>= 1;
if (_boolBits <= 1) _boolBits = (uint)~this.Next();
return (_boolBits & 1) == 0;
}
}