Portanto, há várias maneiras de criar um bool aleatório em C #:
- Usando Random.Next ():
rand.Next(2) == 0
- Usando Random.NextDouble ():
rand.NextDouble() > 0.5
Existe realmente alguma diferença? Em caso afirmativo, qual realmente tem o melhor desempenho? Ou há outra maneira que eu não vi, que pode ser ainda mais rápida?
c#
performance
random
boolean
cronometrado
fonte
fonte
NextBytes
para preencher previamente uma matriz de bytes, usá-laBitArray
para transformá-la em uma coleção de booleanos e recuperar esses booleanos de umQueue
até que seja esvaziado, depois repetir o processo. Com esse método, você está usando o randomizador apenas uma vez, portanto, qualquer sobrecarga que ele crie só acontece quando você reabastece a fila. Isso pode ser útil ao lidar com um gerador de números aleatórios seguro em vez de umaRandom
classe regular .NextBytes
, por isso é surpreendentemente lentobuffer[i] = (byte)(this.InternalSample() % 256);
- Presumo que é disso que você está falando, que eles poderiam ter pegado aquele inteiro aleatório e dividido em 3 bytes , preenchendo a matriz de bytes com cerca de 1/3 do trabalho. Eu me pergunto se houve um motivo para isso ou se foi apenas um descuido dos desenvolvedores.Respostas:
A primeira opção -
rand.Next(2)
executa nos bastidores o seguinte código:if (maxValue < 0) { throw new ArgumentOutOfRangeException("maxValue", Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", new object[] { "maxValue" })); } return (int) (this.Sample() * maxValue);
e para a segunda opção -
rand.NextDouble()
:return this.Sample();
Como a primeira opção contém
maxValue
validação, multiplicação e conversão, a segunda opção é provavelmente mais rápida .fonte
Pequeno aprimoramento para a segunda opção :
De acordo com MSDN
public virtual double NextDouble()
retorna
Então, se você quiser um bool aleatório distribuído uniformemente, você deve usar
>= 0.5
rand.NextDouble() >= 0.5
fonte
O mais rápido. Chamar o método
Random.Next
tem menos sobrecarga. O método de extensão abaixo é executado 20% mais rápido do queRandom.NextDouble() > 0.5
e 35% mais rápido do queRandom.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] }
Mais rápido do que o mais rápido. É possível gerar booleanos aleatórios com a
Random
classe ainda mais rápido, usando truques. Os 31 bits significativos de um geradoint
podem ser usados para 31 produções booleanas subsequentes. A implementação abaixo é 40% mais rápida do que a anteriormente declarada como a mais rápida.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; } }
fonte
Fiz testes com cronômetro. 100.000 iterações:
System.Random rnd = new System.Random(); if (rnd.Next(2) == 0) trues++;
CPUs gostam de inteiros, então o método Next (2) foi mais rápido. 3.700 contra 7.500 ms, o que é bastante significativo. Além disso: eu acho que números aleatórios podem ser um gargalo, criei cerca de 50 cada quadro no Unity, mesmo com uma cena minúscula que tornou meu sistema visivelmente lento, então eu também esperava encontrar um método para criar um bool aleatório. Então eu também tentei
if (System.DateTime.Now.Millisecond % 2 == 0) trues++;
mas chamar uma função estática foi ainda mais lento com 9.600 ms. Vale a pena experimentar. Por fim, pulei a comparação e criei apenas 100.000 valores aleatórios, para ter certeza de que a comparação int vs. dupla não influenciava o tempo decorrido, mas o resultado era praticamente o mesmo.
fonte
DateTime.UtcNow
, é muito mais rápido do queDateTime.Now
.