Random Classe
Definição
Importante
Algumas informações se referem a produtos de pré-lançamento que podem ser substancialmente modificados antes do lançamento. A Microsoft não oferece garantias, expressas ou implícitas, das informações aqui fornecidas.
Representa um gerador de número pseudoaleatório, que é um algoritmo que produz uma sequência de números que atendem a certos requisitos estatísticos de aleatoriedade.
public ref class Random
public class Random
[System.Serializable]
public class Random
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public class Random
type Random = class
[<System.Serializable>]
type Random = class
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type Random = class
Public Class Random
- Herança
-
Random
- Atributos
Exemplos
O exemplo a seguir cria um único gerador de número aleatório e chama seus NextBytesmétodos , Nexte NextDouble para gerar sequências de números aleatórios dentro de intervalos diferentes.
using namespace System;
void main()
{
// Instantiate random number generator using system-supplied value as seed.
Random^ rand = gcnew Random();
// Generate and display 5 random byte (integer) values.
array<Byte>^ bytes = gcnew array<Byte>(4);
rand->NextBytes(bytes);
Console::WriteLine("Five random byte values:");
for each (Byte byteValue in bytes)
Console::Write("{0, 5}", byteValue);
Console::WriteLine();
// Generate and display 5 random integers.
Console::WriteLine("Five random integer values:");
for (int ctr = 0; ctr <= 4; ctr++)
Console::Write("{0,15:N0}", rand->Next());
Console::WriteLine();
// Generate and display 5 random integers between 0 and 100.//
Console::WriteLine("Five random integers between 0 and 100:");
for (int ctr = 0; ctr <= 4; ctr++)
Console::Write("{0,8:N0}", rand->Next(101));
Console::WriteLine();
// Generate and display 5 random integers from 50 to 100.
Console::WriteLine("Five random integers between 50 and 100:");
for (int ctr = 0; ctr <= 4; ctr++)
Console::Write("{0,8:N0}", rand->Next(50, 101));
Console::WriteLine();
// Generate and display 5 random floating point values from 0 to 1.
Console::WriteLine("Five Doubles.");
for (int ctr = 0; ctr <= 4; ctr++)
Console::Write("{0,8:N3}", rand->NextDouble());
Console::WriteLine();
// Generate and display 5 random floating point values from 0 to 5.
Console::WriteLine("Five Doubles between 0 and 5.");
for (int ctr = 0; ctr <= 4; ctr++)
Console::Write("{0,8:N3}", rand->NextDouble() * 5);
}
// The example displays output like the following:
// Five random byte values:
// 194 185 239 54 116
// Five random integer values:
// 507,353,531 1,509,532,693 2,125,074,958 1,409,512,757 652,767,128
// Five random integers between 0 and 100:
// 16 78 94 79 52
// Five random integers between 50 and 100:
// 56 66 96 60 65
// Five Doubles.
// 0.943 0.108 0.744 0.563 0.415
// Five Doubles between 0 and 5.
// 2.934 3.130 0.292 1.432 4.369
// Instantiate random number generator using system-supplied value as seed.
var rand = new Random();
// Generate and display 5 random byte (integer) values.
var bytes = new byte[5];
rand.NextBytes(bytes);
Console.WriteLine("Five random byte values:");
foreach (byte byteValue in bytes)
Console.Write("{0, 5}", byteValue);
Console.WriteLine();
// Generate and display 5 random integers.
Console.WriteLine("Five random integer values:");
for (int ctr = 0; ctr <= 4; ctr++)
Console.Write("{0,15:N0}", rand.Next());
Console.WriteLine();
// Generate and display 5 random integers between 0 and 100.
Console.WriteLine("Five random integers between 0 and 100:");
for (int ctr = 0; ctr <= 4; ctr++)
Console.Write("{0,8:N0}", rand.Next(101));
Console.WriteLine();
// Generate and display 5 random integers from 50 to 100.
Console.WriteLine("Five random integers between 50 and 100:");
for (int ctr = 0; ctr <= 4; ctr++)
Console.Write("{0,8:N0}", rand.Next(50, 101));
Console.WriteLine();
// Generate and display 5 random floating point values from 0 to 1.
Console.WriteLine("Five Doubles.");
for (int ctr = 0; ctr <= 4; ctr++)
Console.Write("{0,8:N3}", rand.NextDouble());
Console.WriteLine();
// Generate and display 5 random floating point values from 0 to 5.
Console.WriteLine("Five Doubles between 0 and 5.");
for (int ctr = 0; ctr <= 4; ctr++)
Console.Write("{0,8:N3}", rand.NextDouble() * 5);
// The example displays output like the following:
// Five random byte values:
// 194 185 239 54 116
// Five random integer values:
// 507,353,531 1,509,532,693 2,125,074,958 1,409,512,757 652,767,128
// Five random integers between 0 and 100:
// 16 78 94 79 52
// Five random integers between 50 and 100:
// 56 66 96 60 65
// Five Doubles.
// 0.943 0.108 0.744 0.563 0.415
// Five Doubles between 0 and 5.
// 2.934 3.130 0.292 1.432 4.369
// Instantiate random number generator using system-supplied value as seed.
let rand = Random()
// Generate and display 5 random byte (integer) values.
let bytes = Array.zeroCreate 5
rand.NextBytes bytes
printfn "Five random byte values:"
for byte in bytes do
printf "%5i" byte
printfn ""
// Generate and display 5 random integers.
printfn "Five random integer values:"
for _ = 0 to 4 do
printf $"{rand.Next(),15:N0}"
printfn ""
// Generate and display 5 random integers between 0 and 100.
printfn "Five random integers between 0 and 100:"
for _ = 0 to 4 do
printf $"{rand.Next 101,8:N0}"
printfn ""
// Generate and display 5 random integers from 50 to 100.
printfn "Five random integers between 50 and 100:"
for _ = 0 to 4 do
printf $"{rand.Next(50, 101),8:N0}"
printfn ""
// Generate and display 5 random floating point values from 0 to 1.
printfn "Five Doubles."
for _ = 0 to 4 do
printf $"{rand.NextDouble(),8:N3}"
printfn ""
// Generate and display 5 random floating point values from 0 to 5.
printfn "Five Doubles between 0 and 5."
for _ = 0 to 4 do
printf $"{rand.NextDouble() * 5.0,8:N3}"
// The example displays output like the following:
// Five random byte values:
// 194 185 239 54 116
// Five random integer values:
// 507,353,531 1,509,532,693 2,125,074,958 1,409,512,757 652,767,128
// Five random integers between 0 and 100:
// 16 78 94 79 52
// Five random integers between 50 and 100:
// 56 66 96 60 65
// Five Doubles.
// 0.943 0.108 0.744 0.563 0.415
// Five Doubles between 0 and 5.
// 2.934 3.130 0.292 1.432 4.369
Module Example
Public Sub Main()
' Instantiate random number generator using system-supplied value as seed.
Dim rand As New Random()
' Generate and display 5 random byte (integer) values.
Dim bytes(4) As Byte
rand.NextBytes(bytes)
Console.WriteLine("Five random byte values:")
For Each byteValue As Byte In bytes
Console.Write("{0, 5}", byteValue)
Next
Console.WriteLine()
' Generate and display 5 random integers.
Console.WriteLine("Five random integer values:")
For ctr As Integer = 0 To 4
Console.Write("{0,15:N0}", rand.Next)
Next
Console.WriteLine()
' Generate and display 5 random integers between 0 and 100.'
Console.WriteLine("Five random integers between 0 and 100:")
For ctr As Integer = 0 To 4
Console.Write("{0,8:N0}", rand.Next(101))
Next
Console.WriteLine()
' Generate and display 5 random integers from 50 to 100.
Console.WriteLine("Five random integers between 50 and 100:")
For ctr As Integer = 0 To 4
Console.Write("{0,8:N0}", rand.Next(50, 101))
Next
Console.WriteLine()
' Generate and display 5 random floating point values from 0 to 1.
Console.WriteLine("Five Doubles.")
For ctr As Integer = 0 To 4
Console.Write("{0,8:N3}", rand.NextDouble())
Next
Console.WriteLine()
' Generate and display 5 random floating point values from 0 to 5.
Console.WriteLine("Five Doubles between 0 and 5.")
For ctr As Integer = 0 To 4
Console.Write("{0,8:N3}", rand.NextDouble() * 5)
Next
End Sub
End Module
' The example displays output like the following:
' Five random byte values:
' 194 185 239 54 116
' Five random integer values:
' 507,353,531 1,509,532,693 2,125,074,958 1,409,512,757 652,767,128
' Five random integers between 0 and 100:
' 16 78 94 79 52
' Five random integers between 50 and 100:
' 56 66 96 60 65
' Five Doubles.
' 0.943 0.108 0.744 0.563 0.415
' Five Doubles between 0 and 5.
' 2.934 3.130 0.292 1.432 4.369
O exemplo a seguir gera um inteiro aleatório que ele usa como um índice para recuperar um valor de cadeia de caracteres de uma matriz.
using namespace System;
void main()
{
Random^ rnd = gcnew Random();
array<String^>^ malePetNames = { "Rufus", "Bear", "Dakota", "Fido",
"Vanya", "Samuel", "Koani", "Volodya",
"Prince", "Yiska" };
array<String^>^ femalePetNames = { "Maggie", "Penny", "Saya", "Princess",
"Abby", "Laila", "Sadie", "Olivia",
"Starlight", "Talla" };
// Generate random indexes for pet names.
int mIndex = rnd->Next(malePetNames->Length);
int fIndex = rnd->Next(femalePetNames->Length);
// Display the result.
Console::WriteLine("Suggested pet name of the day: ");
Console::WriteLine(" For a male: {0}", malePetNames[mIndex]);
Console::WriteLine(" For a female: {0}", femalePetNames[fIndex]);
}
// The example displays output similar to the following:
// Suggested pet name of the day:
// For a male: Koani
// For a female: Maggie
Random rnd = new Random();
string[] malePetNames = { "Rufus", "Bear", "Dakota", "Fido",
"Vanya", "Samuel", "Koani", "Volodya",
"Prince", "Yiska" };
string[] femalePetNames = { "Maggie", "Penny", "Saya", "Princess",
"Abby", "Laila", "Sadie", "Olivia",
"Starlight", "Talla" };
// Generate random indexes for pet names.
int mIndex = rnd.Next(malePetNames.Length);
int fIndex = rnd.Next(femalePetNames.Length);
// Display the result.
Console.WriteLine("Suggested pet name of the day: ");
Console.WriteLine(" For a male: {0}", malePetNames[mIndex]);
Console.WriteLine(" For a female: {0}", femalePetNames[fIndex]);
// The example displays output similar to the following:
// Suggested pet name of the day:
// For a male: Koani
// For a female: Maggie
let rnd = Random()
let malePetNames =
[| "Rufus"; "Bear"; "Dakota"; "Fido";
"Vanya"; "Samuel"; "Koani"; "Volodya";
"Prince"; "Yiska" |]
let femalePetNames =
[| "Maggie"; "Penny"; "Saya"; "Princess";
"Abby"; "Laila"; "Sadie"; "Olivia";
"Starlight"; "Talla" |]
// Generate random indexes for pet names.
let mIndex = rnd.Next malePetNames.Length
let fIndex = rnd.Next femalePetNames.Length
// Display the result.
printfn "Suggested pet name of the day: "
printfn " For a male: %s" malePetNames.[mIndex]
printfn " For a female: %s" femalePetNames.[fIndex]
// The example displays output similar to the following:
// Suggested pet name of the day:
// For a male: Koani
// For a female: Maggie
Module Example
Public Sub Main()
Dim rnd As New Random()
Dim malePetNames() As String = { "Rufus", "Bear", "Dakota", "Fido",
"Vanya", "Samuel", "Koani", "Volodya",
"Prince", "Yiska" }
Dim femalePetNames() As String = { "Maggie", "Penny", "Saya", "Princess",
"Abby", "Laila", "Sadie", "Olivia",
"Starlight", "Talla" }
' Generate random indexes for pet names.
Dim mIndex As Integer = rnd.Next(malePetNames.Length)
Dim fIndex As Integer = rnd.Next(femalePetNames.Length)
' Display the result.
Console.WriteLine("Suggested pet name of the day: ")
Console.WriteLine(" For a male: {0}", malePetNames(mIndex))
Console.WriteLine(" For a female: {0}", femalePetNames(fIndex))
End Sub
End Module
' The example displays output similar to the following:
' Suggested pet name of the day:
' For a male: Koani
' For a female: Maggie
Comentários
Números pseudo-aleatórios são escolhidos com a mesma probabilidade de um conjunto finito de números. Os números escolhidos não são completamente aleatórios porque um algoritmo matemático é usado para selecioná-los, mas são suficientemente aleatórios para fins práticos. A implementação atual da Random classe baseia-se em uma versão modificada do algoritmo de gerador de número aleatório subtrativo de Donald E. Knuth. Para obter mais informações, consulte D. E. Knuth. A arte da programação de computador, Volume 2: Algoritmos seminuméricos. Addison-Wesley, Reading, MA, terceira edição, 1997.
Para gerar um número aleatório criptograficamente seguro, como um que seja adequado para criar uma senha aleatória, use a RNGCryptoServiceProvider classe ou derive uma classe de System.Security.Cryptography.RandomNumberGenerator.
Neste tópico:
Instanciando o gerador de número aleatório
Evitando várias instanciações
A classe System.Random e a segurança de thread
Gerando diferentes tipos de números aleatórios
Substituindo seu próprio algoritmo
Como você usa System.Random para...
Recuperar a mesma sequência de valores aleatórios
Recuperar sequências exclusivas de valores aleatórios
Recuperar inteiros em um intervalo especificado
Recuperar inteiros com um número especificado de dígitos
Recuperar valores de ponto flutuante em um intervalo especificado
Gerar valores boolianos aleatórios
Gerar inteiros aleatórios de 64 bits
Recuperar bytes em um intervalo especificado
Recuperar um elemento de uma matriz ou coleção aleatoriamente
Recuperar um elemento exclusivo de uma matriz ou coleção
Instanciando o gerador de número aleatório
Você cria uma instância do gerador de números aleatórios fornecendo um valor de semente (um valor inicial para o algoritmo de geração de número pseudo-aleatório) para um Random construtor de classe. Você pode fornecer o valor de semente explicitamente ou implicitamente:
O Random(Int32) construtor usa um valor de semente explícito que você fornece.
O Random() construtor usa o valor de semente padrão. Essa é a maneira mais comum de instanciar o gerador de número aleatório.
Em .NET Framework, o valor de semente padrão depende de tempo. No .NET Core, o valor de semente padrão é produzido pelo gerador de números pseudo-aleatórios e estáticos do thread.
Se a mesma semente for usada para objetos separados Random , elas gerarão a mesma série de números aleatórios. Isso pode ser útil para criar um conjunto de testes que processa valores aleatórios ou para reproduzir jogos que derivam seus dados de números aleatórios. No entanto, observe que Random os objetos em processos em execução em diferentes versões do .NET Framework podem retornar séries diferentes de números aleatórios, mesmo que sejam instanciados com valores de semente idênticos.
Para produzir sequências diferentes de números aleatórios, você pode tornar o valor da semente dependente de tempo, produzindo assim uma série diferente com cada nova instância de Random. O construtor parametrizado Random(Int32) pode ter um Int32 valor com base no número de tiques no momento atual, enquanto o construtor sem Random() parâmetros usa o relógio do sistema para gerar seu valor de semente. No entanto, no .NET Framework apenas porque o relógio tem resolução finita, usar o construtor sem parâmetros para criar objetos diferentes Random em sucessão próxima cria geradores de número aleatório que produzem sequências idênticas de números aleatórios. O exemplo a seguir ilustra como dois Random objetos instanciados em sucessão próxima em um aplicativo .NET Framework geram uma série idêntica de números aleatórios. Na maioria dos sistemas Windows, Random os objetos criados dentro de 15 milissegundos um do outro provavelmente têm valores de semente idênticos.
using namespace System;
void main()
{
array<Byte>^ bytes1 = gcnew array<Byte>(100);
array<Byte>^ bytes2 = gcnew array<Byte>(100);
Random^ rnd1 = gcnew Random();
Random^ rnd2 = gcnew Random();
rnd1->NextBytes(bytes1);
rnd2->NextBytes(bytes2);
Console::WriteLine("First Series:");
for (int ctr = bytes1->GetLowerBound(0);
ctr <= bytes1->GetUpperBound(0);
ctr++) {
Console::Write("{0, 5}", bytes1[ctr]);
if ((ctr + 1) % 10 == 0) Console::WriteLine();
}
Console::WriteLine();
Console::WriteLine("Second Series:");
for (int ctr = bytes2->GetLowerBound(0);
ctr <= bytes2->GetUpperBound(0);
ctr++) {
Console::Write("{0, 5}", bytes2[ctr]);
if ((ctr + 1) % 10 == 0) Console::WriteLine();
}
}
// The example displays output like the following:
// First Series:
// 97 129 149 54 22 208 120 105 68 177
// 113 214 30 172 74 218 116 230 89 18
// 12 112 130 105 116 180 190 200 187 120
// 7 198 233 158 58 51 50 170 98 23
// 21 1 113 74 146 245 34 255 96 24
// 232 255 23 9 167 240 255 44 194 98
// 18 175 173 204 169 171 236 127 114 23
// 167 202 132 65 253 11 254 56 214 127
// 145 191 104 163 143 7 174 224 247 73
// 52 6 231 255 5 101 83 165 160 231
//
// Second Series:
// 97 129 149 54 22 208 120 105 68 177
// 113 214 30 172 74 218 116 230 89 18
// 12 112 130 105 116 180 190 200 187 120
// 7 198 233 158 58 51 50 170 98 23
// 21 1 113 74 146 245 34 255 96 24
// 232 255 23 9 167 240 255 44 194 98
// 18 175 173 204 169 171 236 127 114 23
// 167 202 132 65 253 11 254 56 214 127
// 145 191 104 163 143 7 174 224 247 73
// 52 6 231 255 5 101 83 165 160 231
byte[] bytes1 = new byte[100];
byte[] bytes2 = new byte[100];
Random rnd1 = new Random();
Random rnd2 = new Random();
rnd1.NextBytes(bytes1);
rnd2.NextBytes(bytes2);
Console.WriteLine("First Series:");
for (int ctr = bytes1.GetLowerBound(0);
ctr <= bytes1.GetUpperBound(0);
ctr++) {
Console.Write("{0, 5}", bytes1[ctr]);
if ((ctr + 1) % 10 == 0) Console.WriteLine();
}
Console.WriteLine();
Console.WriteLine("Second Series:");
for (int ctr = bytes2.GetLowerBound(0);
ctr <= bytes2.GetUpperBound(0);
ctr++) {
Console.Write("{0, 5}", bytes2[ctr]);
if ((ctr + 1) % 10 == 0) Console.WriteLine();
}
// The example displays output like the following:
// First Series:
// 97 129 149 54 22 208 120 105 68 177
// 113 214 30 172 74 218 116 230 89 18
// 12 112 130 105 116 180 190 200 187 120
// 7 198 233 158 58 51 50 170 98 23
// 21 1 113 74 146 245 34 255 96 24
// 232 255 23 9 167 240 255 44 194 98
// 18 175 173 204 169 171 236 127 114 23
// 167 202 132 65 253 11 254 56 214 127
// 145 191 104 163 143 7 174 224 247 73
// 52 6 231 255 5 101 83 165 160 231
//
// Second Series:
// 97 129 149 54 22 208 120 105 68 177
// 113 214 30 172 74 218 116 230 89 18
// 12 112 130 105 116 180 190 200 187 120
// 7 198 233 158 58 51 50 170 98 23
// 21 1 113 74 146 245 34 255 96 24
// 232 255 23 9 167 240 255 44 194 98
// 18 175 173 204 169 171 236 127 114 23
// 167 202 132 65 253 11 254 56 214 127
// 145 191 104 163 143 7 174 224 247 73
// 52 6 231 255 5 101 83 165 160 231
let bytes1 = Array.zeroCreate 100
let bytes2 = Array.zeroCreate 100
let rnd1 = Random()
let rnd2 = Random()
rnd1.NextBytes bytes1
rnd2.NextBytes bytes2
printfn "First Series"
for i = bytes1.GetLowerBound 0 to bytes1.GetUpperBound 0 do
printf "%5i" bytes1.[i]
if (i + 1) % 10 = 0 then printfn ""
printfn ""
printfn "Second Series"
for i = bytes2.GetLowerBound 0 to bytes2.GetUpperBound 0 do
printf "%5i" bytes2.[i]
if (i + 1) % 10 = 0 then printfn ""
// The example displays output like the following:
// First Series:
// 97 129 149 54 22 208 120 105 68 177
// 113 214 30 172 74 218 116 230 89 18
// 12 112 130 105 116 180 190 200 187 120
// 7 198 233 158 58 51 50 170 98 23
// 21 1 113 74 146 245 34 255 96 24
// 232 255 23 9 167 240 255 44 194 98
// 18 175 173 204 169 171 236 127 114 23
// 167 202 132 65 253 11 254 56 214 127
// 145 191 104 163 143 7 174 224 247 73
// 52 6 231 255 5 101 83 165 160 231
//
// Second Series:
// 97 129 149 54 22 208 120 105 68 177
// 113 214 30 172 74 218 116 230 89 18
// 12 112 130 105 116 180 190 200 187 120
// 7 198 233 158 58 51 50 170 98 23
// 21 1 113 74 146 245 34 255 96 24
// 232 255 23 9 167 240 255 44 194 98
// 18 175 173 204 169 171 236 127 114 23
// 167 202 132 65 253 11 254 56 214 127
// 145 191 104 163 143 7 174 224 247 73
// 52 6 231 255 5 101 83 165 160 231
Module modMain
Public Sub Main()
Dim bytes1(99), bytes2(99) As Byte
Dim rnd1 As New Random()
Dim rnd2 As New Random()
rnd1.NextBytes(bytes1)
rnd2.NextBytes(bytes2)
Console.WriteLine("First Series:")
For ctr As Integer = bytes1.GetLowerBound(0) to bytes1.GetUpperBound(0)
Console.Write("{0, 5}", bytes1(ctr))
If (ctr + 1) Mod 10 = 0 Then Console.WriteLine()
Next
Console.WriteLine()
Console.WriteLine("Second Series:")
For ctr As Integer = bytes2.GetLowerBound(0) to bytes2.GetUpperBound(0)
Console.Write("{0, 5}", bytes2(ctr))
If (ctr + 1) Mod 10 = 0 Then Console.WriteLine()
Next
End Sub
End Module
' The example displays output like the following:
' First Series:
' 97 129 149 54 22 208 120 105 68 177
' 113 214 30 172 74 218 116 230 89 18
' 12 112 130 105 116 180 190 200 187 120
' 7 198 233 158 58 51 50 170 98 23
' 21 1 113 74 146 245 34 255 96 24
' 232 255 23 9 167 240 255 44 194 98
' 18 175 173 204 169 171 236 127 114 23
' 167 202 132 65 253 11 254 56 214 127
' 145 191 104 163 143 7 174 224 247 73
' 52 6 231 255 5 101 83 165 160 231
'
' Second Series:
' 97 129 149 54 22 208 120 105 68 177
' 113 214 30 172 74 218 116 230 89 18
' 12 112 130 105 116 180 190 200 187 120
' 7 198 233 158 58 51 50 170 98 23
' 21 1 113 74 146 245 34 255 96 24
' 232 255 23 9 167 240 255 44 194 98
' 18 175 173 204 169 171 236 127 114 23
' 167 202 132 65 253 11 254 56 214 127
' 145 191 104 163 143 7 174 224 247 73
' 52 6 231 255 5 101 83 165 160 231
Para evitar esse problema, crie um único Random objeto em vez de vários objetos. Observe que a Random
classe no .NET Core não tem essa limitação.
Evitando várias instanciações
No .NET Framework, inicializar dois geradores de número aleatório em um loop apertado ou em sucessão rápida cria dois geradores de número aleatório que podem produzir sequências idênticas de números aleatórios. Na maioria dos casos, essa não é a intenção do desenvolvedor e pode levar a problemas de desempenho, pois instanciar e inicializar um gerador de número aleatório é um processo relativamente caro.
Para melhorar o desempenho e evitar a criação inadvertida de geradores de números aleatórios separados que geram sequências numéricas idênticas, recomendamos que você crie um Random objeto para gerar muitos números aleatórios ao longo do tempo, em vez de criar novos Random objetos para gerar um número aleatório.
No entanto, a Random classe não é thread-safe. Se você chamar Random métodos de vários threads, siga as diretrizes discutidas na próxima seção.
A classe System.Random e a segurança de thread
Em vez de instanciar objetos individuais Random , recomendamos que você crie uma única Random instância para gerar todos os números aleatórios necessários para seu aplicativo. No entanto, Random os objetos não são thread-safe. Se o aplicativo chamar Random métodos de vários threads, você deverá usar um objeto de sincronização para garantir que apenas um thread possa acessar o gerador de número aleatório por vez. Se você não garantir que o Random objeto seja acessado de maneira thread-safe, as chamadas para métodos que retornam números aleatórios retornarão 0.
O exemplo a seguir usa a Instrução de bloqueio C#, a função de bloqueio F# e a instrução SyncLock do Visual Basic para garantir que um único gerador de número aleatório seja acessado por 11 threads de maneira thread-safe. Cada thread gera 2 milhões de números aleatórios, conta o número de números aleatórios gerados e calcula sua soma e atualiza os totais de todos os threads quando termina de executar.
using namespace System;
using namespace System::Threading;
ref class Example
{
private:
[ThreadStatic] static double previous = 0.0;
[ThreadStatic] static int perThreadCtr = 0;
[ThreadStatic] static double perThreadTotal = 0.0;
static CancellationTokenSource^ source;
static CountdownEvent^ countdown;
static Object^ randLock;
static Object^ numericLock;
static Random^ rand;
double totalValue = 0.0;
int totalCount = 0;
public:
Example()
{
rand = gcnew Random();
randLock = gcnew Object();
numericLock = gcnew Object();
countdown = gcnew CountdownEvent(1);
source = gcnew CancellationTokenSource();
}
void Execute()
{
CancellationToken^ token = source->Token;
for (int threads = 1; threads <= 10; threads++)
{
Thread^ newThread = gcnew Thread(gcnew ParameterizedThreadStart(this, &Example::GetRandomNumbers));
newThread->Name = threads.ToString();
newThread->Start(token);
}
this->GetRandomNumbers(token);
countdown->Signal();
// Make sure all threads have finished.
countdown->Wait();
Console::WriteLine("\nTotal random numbers generated: {0:N0}", totalCount);
Console::WriteLine("Total sum of all random numbers: {0:N2}", totalValue);
Console::WriteLine("Random number mean: {0:N4}", totalValue/totalCount);
}
private:
void GetRandomNumbers(Object^ o)
{
CancellationToken^ token = (CancellationToken) o;
double result = 0.0;
countdown->AddCount(1);
try {
for (int ctr = 0; ctr < 2000000; ctr++)
{
// Make sure there's no corruption of Random.
token->ThrowIfCancellationRequested();
Monitor::Enter(randLock);
result = rand->NextDouble();
Monitor::Exit(randLock);
// Check for corruption of Random instance.
if ((result == previous) && result == 0) {
source->Cancel();
}
else {
previous = result;
}
perThreadCtr++;
perThreadTotal += result;
}
Console::WriteLine("Thread {0} finished execution.",
Thread::CurrentThread->Name);
Console::WriteLine("Random numbers generated: {0:N0}", perThreadCtr);
Console::WriteLine("Sum of random numbers: {0:N2}", perThreadTotal);
Console::WriteLine("Random number mean: {0:N4}\n", perThreadTotal/perThreadCtr);
// Update overall totals.
Monitor::Enter(numericLock);
totalCount += perThreadCtr;
totalValue += perThreadTotal;
Monitor::Exit(numericLock);
}
catch (OperationCanceledException^ e) {
Console::WriteLine("Corruption in Thread {1}", e->GetType()->Name,
Thread::CurrentThread->Name);
}
finally {
countdown->Signal();
}
}
};
void main()
{
Example^ ex = gcnew Example();
Thread::CurrentThread->Name = "Main";
ex->Execute();
}
// The example displays output like the following:
// Thread 6 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,491.05
// Random number mean: 0.5002
//
// Thread 10 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,329.64
// Random number mean: 0.4997
//
// Thread 4 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,166.89
// Random number mean: 0.5001
//
// Thread 8 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,628.37
// Random number mean: 0.4998
//
// Thread Main finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,920.89
// Random number mean: 0.5000
//
// Thread 3 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,370.45
// Random number mean: 0.4997
//
// Thread 7 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,330.92
// Random number mean: 0.4997
//
// Thread 9 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,172.79
// Random number mean: 0.5001
//
// Thread 5 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,079.43
// Random number mean: 0.5000
//
// Thread 1 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,817.91
// Random number mean: 0.4999
//
// Thread 2 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,930.63
// Random number mean: 0.5000
//
//
// Total random numbers generated: 22,000,000
// Total sum of all random numbers: 10,998,238.98
// Random number mean: 0.4999
using System;
using System.Threading;
public class Example
{
[ThreadStatic] static double previous = 0.0;
[ThreadStatic] static int perThreadCtr = 0;
[ThreadStatic] static double perThreadTotal = 0.0;
static CancellationTokenSource source;
static CountdownEvent countdown;
static Object randLock, numericLock;
static Random rand;
double totalValue = 0.0;
int totalCount = 0;
public Example()
{
rand = new Random();
randLock = new Object();
numericLock = new Object();
countdown = new CountdownEvent(1);
source = new CancellationTokenSource();
}
public static void Main()
{
Example ex = new Example();
Thread.CurrentThread.Name = "Main";
ex.Execute();
}
private void Execute()
{
CancellationToken token = source.Token;
for (int threads = 1; threads <= 10; threads++)
{
Thread newThread = new Thread(this.GetRandomNumbers);
newThread.Name = threads.ToString();
newThread.Start(token);
}
this.GetRandomNumbers(token);
countdown.Signal();
// Make sure all threads have finished.
countdown.Wait();
source.Dispose();
Console.WriteLine("\nTotal random numbers generated: {0:N0}", totalCount);
Console.WriteLine("Total sum of all random numbers: {0:N2}", totalValue);
Console.WriteLine("Random number mean: {0:N4}", totalValue/totalCount);
}
private void GetRandomNumbers(Object o)
{
CancellationToken token = (CancellationToken) o;
double result = 0.0;
countdown.AddCount(1);
try {
for (int ctr = 0; ctr < 2000000; ctr++)
{
// Make sure there's no corruption of Random.
token.ThrowIfCancellationRequested();
lock (randLock) {
result = rand.NextDouble();
}
// Check for corruption of Random instance.
if ((result == previous) && result == 0) {
source.Cancel();
}
else {
previous = result;
}
perThreadCtr++;
perThreadTotal += result;
}
Console.WriteLine("Thread {0} finished execution.",
Thread.CurrentThread.Name);
Console.WriteLine("Random numbers generated: {0:N0}", perThreadCtr);
Console.WriteLine("Sum of random numbers: {0:N2}", perThreadTotal);
Console.WriteLine("Random number mean: {0:N4}\n", perThreadTotal/perThreadCtr);
// Update overall totals.
lock (numericLock) {
totalCount += perThreadCtr;
totalValue += perThreadTotal;
}
}
catch (OperationCanceledException e) {
Console.WriteLine("Corruption in Thread {1}", e.GetType().Name, Thread.CurrentThread.Name);
}
finally {
countdown.Signal();
}
}
}
// The example displays output like the following:
// Thread 6 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,491.05
// Random number mean: 0.5002
//
// Thread 10 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,329.64
// Random number mean: 0.4997
//
// Thread 4 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,166.89
// Random number mean: 0.5001
//
// Thread 8 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,628.37
// Random number mean: 0.4998
//
// Thread Main finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,920.89
// Random number mean: 0.5000
//
// Thread 3 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,370.45
// Random number mean: 0.4997
//
// Thread 7 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,330.92
// Random number mean: 0.4997
//
// Thread 9 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,172.79
// Random number mean: 0.5001
//
// Thread 5 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,079.43
// Random number mean: 0.5000
//
// Thread 1 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,817.91
// Random number mean: 0.4999
//
// Thread 2 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,930.63
// Random number mean: 0.5000
//
//
// Total random numbers generated: 22,000,000
// Total sum of all random numbers: 10,998,238.98
// Random number mean: 0.4999
open System
open System.Threading
type Example() =
[<ThreadStatic; DefaultValue>]
static val mutable private previous : float
[<ThreadStatic; DefaultValue>]
static val mutable private perThreadCtr : int
[<ThreadStatic; DefaultValue>]
static val mutable private perThreadTotal : float
static let source = new CancellationTokenSource()
static let countdown = new CountdownEvent(1)
static let randLock = obj ()
static let numericLock = obj ()
static let rand = Random()
let mutable totalValue = 0.0
let mutable totalCount = 0
member _.GetRandomNumbers(token: CancellationToken) =
let mutable result = 0.0
countdown.AddCount 1
try
try
for _ = 0 to 1999999 do
// Make sure there's no corruption of Random.
token.ThrowIfCancellationRequested()
lock randLock (fun () ->
result <- rand.NextDouble() )
// Check for corruption of Random instance.
if result = Example.previous && result = 0.0 then
source.Cancel()
else
Example.previous <- result
Example.perThreadCtr <- Example.perThreadCtr + 1
Example.perThreadTotal <- Example.perThreadTotal + result
// Update overall totals.
lock numericLock (fun () ->
// Show result.
printfn "Thread %s finished execution." Thread.CurrentThread.Name
printfn $"Random numbers generated: {Example.perThreadCtr:N0}"
printfn $"Sum of random numbers: {Example.perThreadTotal:N2}"
printfn $"Random number mean: {(Example.perThreadTotal / float Example.perThreadCtr):N4}\n"
// Update overall totals.
totalCount <- totalCount + Example.perThreadCtr
totalValue <- totalValue + Example.perThreadTotal)
with :? OperationCanceledException as e ->
printfn "Corruption in Thread %s %s" (e.GetType().Name) Thread.CurrentThread.Name
finally
countdown.Signal() |> ignore
member this.Execute() =
let token = source.Token
for i = 1 to 10 do
let newThread = Thread(fun () -> this.GetRandomNumbers token)
newThread.Name <- string i
newThread.Start()
this.GetRandomNumbers token
countdown.Signal() |> ignore
countdown.Wait()
source.Dispose()
printfn $"\nTotal random numbers generated: {totalCount:N0}"
printfn $"Total sum of all random numbers: {totalValue:N2}"
printfn $"Random number mean: {(totalValue / float totalCount):N4}"
let ex = Example()
Thread.CurrentThread.Name <- "Main"
ex.Execute()
// The example displays output like the following:
// Thread 6 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,491.05
// Random number mean: 0.5002
//
// Thread 10 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,329.64
// Random number mean: 0.4997
//
// Thread 4 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,166.89
// Random number mean: 0.5001
//
// Thread 8 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,628.37
// Random number mean: 0.4998
//
// Thread Main finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,920.89
// Random number mean: 0.5000
//
// Thread 3 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,370.45
// Random number mean: 0.4997
//
// Thread 7 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,330.92
// Random number mean: 0.4997
//
// Thread 9 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,172.79
// Random number mean: 0.5001
//
// Thread 5 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,079.43
// Random number mean: 0.5000
//
// Thread 1 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,817.91
// Random number mean: 0.4999
//
// Thread 2 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,930.63
// Random number mean: 0.5000
//
//
// Total random numbers generated: 22,000,000
// Total sum of all random numbers: 10,998,238.98
// Random number mean: 0.4999
Imports System.Threading
Module Example
<ThreadStatic> Dim previous As Double = 0.0
<ThreadStatic> Dim perThreadCtr As Integer = 0
<ThreadStatic> Dim perThreadTotal As Double = 0.0
Dim source As New CancellationTokenSource()
Dim countdown As New CountdownEvent(1)
Dim randLock As New Object()
Dim numericLock As New Object()
Dim rand As New Random()
Dim totalValue As Double = 0.0
Dim totalCount As Integer = 0
Public Sub Main()
Thread.CurrentThread.Name = "Main"
Dim token As CancellationToken = source.Token
For threads As Integer = 1 To 10
Dim newThread As New Thread(AddressOf GetRandomNumbers)
newThread.Name = threads.ToString()
newThread.Start(token)
Next
GetRandomNumbers(token)
countdown.Signal()
' Make sure all threads have finished.
countdown.Wait()
Console.WriteLine()
Console.WriteLine("Total random numbers generated: {0:N0}", totalCount)
Console.WriteLine("Total sum of all random numbers: {0:N2}", totalValue)
Console.WriteLine("Random number mean: {0:N4}", totalValue/totalCount)
End Sub
Private Sub GetRandomNumbers(o As Object)
Dim token As CancellationToken = CType(o, CancellationToken)
Dim result As Double = 0.0
countdown.AddCount(1)
Try
For ctr As Integer = 1 To 2000000
' Make sure there's no corruption of Random.
token.ThrowIfCancellationRequested()
SyncLock randLock
result = rand.NextDouble()
End SyncLock
' Check for corruption of Random instance.
If result = previous AndAlso result = 0 Then
source.Cancel()
Else
previous = result
End If
perThreadCtr += 1
perThreadTotal += result
Next
Console.WriteLine("Thread {0} finished execution.",
Thread.CurrentThread.Name)
Console.WriteLine("Random numbers generated: {0:N0}", perThreadCtr)
Console.WriteLine("Sum of random numbers: {0:N2}", perThreadTotal)
Console.WriteLine("Random number mean: {0:N4}", perThreadTotal/perThreadCtr)
Console.WriteLine()
' Update overall totals.
SyncLock numericLock
totalCount += perThreadCtr
totalValue += perThreadTotal
End SyncLock
Catch e As OperationCanceledException
Console.WriteLine("Corruption in Thread {1}", e.GetType().Name, Thread.CurrentThread.Name)
Finally
countdown.Signal()
source.Dispose()
End Try
End Sub
End Module
' The example displays output like the following:
' Thread 6 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 1,000,491.05
' Random number mean: 0.5002
'
' Thread 10 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,329.64
' Random number mean: 0.4997
'
' Thread 4 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 1,000,166.89
' Random number mean: 0.5001
'
' Thread 8 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,628.37
' Random number mean: 0.4998
'
' Thread Main finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,920.89
' Random number mean: 0.5000
'
' Thread 3 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,370.45
' Random number mean: 0.4997
'
' Thread 7 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,330.92
' Random number mean: 0.4997
'
' Thread 9 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 1,000,172.79
' Random number mean: 0.5001
'
' Thread 5 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 1,000,079.43
' Random number mean: 0.5000
'
' Thread 1 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,817.91
' Random number mean: 0.4999
'
' Thread 2 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,930.63
' Random number mean: 0.5000
'
'
' Total random numbers generated: 22,000,000
' Total sum of all random numbers: 10,998,238.98
' Random number mean: 0.4999
O exemplo garante o thread-safety das seguintes maneiras:
O ThreadStaticAttribute atributo é usado para definir variáveis locais de thread que acompanham o número total de números aleatórios gerados e sua soma para cada thread.
Um bloqueio (a instrução
lock
em C#, alock
função em F# e aSyncLock
instrução no Visual Basic) protege o acesso às variáveis para a contagem total e a soma de todos os números aleatórios gerados em todos os threads.Um semáforo (o CountdownEvent objeto) é usado para garantir que o thread main seja bloqueado até que todos os outros threads concluam a execução.
O exemplo verifica se o gerador de número aleatório foi corrompido determinando se duas chamadas consecutivas para métodos de geração de número aleatório retornam 0. Se a corrupção for detectada, o exemplo usará o CancellationTokenSource objeto para sinalizar que todos os threads devem ser cancelados.
Antes de gerar cada número aleatório, cada thread verifica o estado do CancellationToken objeto. Se o cancelamento for solicitado, o exemplo chamará o CancellationToken.ThrowIfCancellationRequested método para cancelar o thread.
O exemplo a seguir é idêntico ao primeiro, exceto que ele usa um Task objeto e uma expressão lambda em vez de Thread objetos.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
static Object randLock, numericLock;
static Random rand;
static CancellationTokenSource source;
double totalValue = 0.0;
int totalCount = 0;
public Example()
{
rand = new Random();
randLock = new Object();
numericLock = new Object();
source = new CancellationTokenSource();
}
public static async Task Main()
{
Example ex = new Example();
Thread.CurrentThread.Name = "Main";
await ex.Execute();
}
private Task Execute()
{
List<Task> tasks = new List<Task>();
for (int ctr = 0; ctr <= 10; ctr++)
{
CancellationToken token = source.Token;
int taskNo = ctr;
tasks.Add(Task.Run( () =>
{
double previous = 0.0;
int taskCtr = 0;
double taskTotal = 0.0;
double result = 0.0;
for (int n = 0; n < 2000000; n++)
{
// Make sure there's no corruption of Random.
token.ThrowIfCancellationRequested();
lock (randLock) {
result = rand.NextDouble();
}
// Check for corruption of Random instance.
if ((result == previous) && result == 0) {
source.Cancel();
}
else {
previous = result;
}
taskCtr++;
taskTotal += result;
}
// Show result.
Console.WriteLine("Task {0} finished execution.", taskNo);
Console.WriteLine("Random numbers generated: {0:N0}", taskCtr);
Console.WriteLine("Sum of random numbers: {0:N2}", taskTotal);
Console.WriteLine("Random number mean: {0:N4}\n", taskTotal/taskCtr);
// Update overall totals.
lock (numericLock) {
totalCount += taskCtr;
totalValue += taskTotal;
}
},
token));
}
try {
await Task.WhenAll(tasks.ToArray());
Console.WriteLine("\nTotal random numbers generated: {0:N0}", totalCount);
Console.WriteLine("Total sum of all random numbers: {0:N2}", totalValue);
Console.WriteLine("Random number mean: {0:N4}", totalValue/totalCount);
}
catch (AggregateException e) {
foreach (Exception inner in e.InnerExceptions) {
TaskCanceledException canc = inner as TaskCanceledException;
if (canc != null)
Console.WriteLine("Task #{0} cancelled.", canc.Task.Id);
else
Console.WriteLine("Exception: {0}", inner.GetType().Name);
}
}
finally {
source.Dispose();
}
}
}
// The example displays output like the following:
// Task 1 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,502.47
// Random number mean: 0.5003
//
// Task 0 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,445.63
// Random number mean: 0.5002
//
// Task 2 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,556.04
// Random number mean: 0.5003
//
// Task 3 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,178.87
// Random number mean: 0.5001
//
// Task 4 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,819.17
// Random number mean: 0.4999
//
// Task 5 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,190.58
// Random number mean: 0.5001
//
// Task 6 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,720.21
// Random number mean: 0.4999
//
// Task 7 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,000.96
// Random number mean: 0.4995
//
// Task 8 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,499.33
// Random number mean: 0.4997
//
// Task 9 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,193.25
// Random number mean: 0.5001
//
// Task 10 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,960.82
// Random number mean: 0.5000
//
//
// Total random numbers generated: 22,000,000
// Total sum of all random numbers: 11,000,067.33
// Random number mean: 0.5000
open System
open System.Threading
open System.Threading.Tasks
type Example() =
static let source = new CancellationTokenSource()
static let rand = Random()
static let randLock = obj ()
static let numericLock = obj ()
let mutable totalValue = 0.0
let mutable totalCount = 0
member _.Execute() =
use source = source // Dispose of the CancellationTokenSource when we're done with it.
let token = source.Token
let tasks =
[| for i = 0 to 10 do
Task.Run(
(fun () ->
let mutable previous = 0.0
let mutable taskCtr = 0
let mutable taskTotal = 0.0
let mutable result = 0.0
for _ = 1 to 2000000 do
// Make sure there's no corruption of Random.
token.ThrowIfCancellationRequested()
lock randLock (fun () -> result <- rand.NextDouble())
// Check for corruption of Random instance.
if result = previous && result = 0.0 then
source.Cancel()
else
previous <- result
taskCtr <- taskCtr + 1
taskTotal <- taskTotal + result
lock numericLock (fun () ->
// Show result.
printfn "Task %i finished execution." i
printfn $"Random numbers generated: {taskCtr:N0}"
printfn $"Sum of random numbers: {taskTotal:N2}"
printfn $"Random number mean: {(taskTotal / float taskCtr):N4}\n"
// Update overall totals.
totalCount <- totalCount + taskCtr
totalValue <- totalValue + taskTotal)),
token
) |]
try
// Run tasks with F# Async.
Task.WhenAll tasks
|> Async.AwaitTask
|> Async.RunSynchronously
printfn $"\nTotal random numbers generated: {totalCount:N0}"
printfn $"Total sum of all random numbers: {totalValue:N2}"
printfn $"Random number mean: {(totalValue / float totalCount):N4}"
with
| :? AggregateException as e ->
for inner in e.InnerExceptions do
match inner with
| :? TaskCanceledException as canc ->
if canc <> null then
printfn $"Task #{canc.Task.Id} cancelled"
else
printfn $"Exception: {inner.GetType().Name}"
| _ -> ()
let ex = Example()
Thread.CurrentThread.Name <- "Main"
ex.Execute()
// The example displays output like the following:
// Task 1 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,502.47
// Random number mean: 0.5003
//
// Task 0 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,445.63
// Random number mean: 0.5002
//
// Task 2 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,556.04
// Random number mean: 0.5003
//
// Task 3 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,178.87
// Random number mean: 0.5001
//
// Task 4 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,819.17
// Random number mean: 0.4999
//
// Task 5 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,190.58
// Random number mean: 0.5001
//
// Task 6 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,720.21
// Random number mean: 0.4999
//
// Task 7 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,000.96
// Random number mean: 0.4995
//
// Task 8 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,499.33
// Random number mean: 0.4997
//
// Task 9 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 1,000,193.25
// Random number mean: 0.5001
//
// Task 10 finished execution.
// Random numbers generated: 2,000,000
// Sum of random numbers: 999,960.82
// Random number mean: 0.5000
//
//
// Total random numbers generated: 22,000,000
// Total sum of all random numbers: 11,000,067.33
// Random number mean: 0.5000
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks
Module Example
Dim source As New CancellationTokenSource()
Dim randLock As New Object()
Dim numericLock As New Object()
Dim rand As New Random()
Dim totalValue As Double = 0.0
Dim totalCount As Integer = 0
Public Sub Main()
Dim tasks As New List(Of Task)()
For ctr As Integer = 1 To 10
Dim token As CancellationToken = source.Token
Dim taskNo As Integer = ctr
tasks.Add(Task.Run(
Sub()
Dim previous As Double = 0.0
Dim taskCtr As Integer = 0
Dim taskTotal As Double = 0.0
Dim result As Double = 0.0
For n As Integer = 1 To 2000000
' Make sure there's no corruption of Random.
token.ThrowIfCancellationRequested()
SyncLock randLock
result = rand.NextDouble()
End SyncLock
' Check for corruption of Random instance.
If result = previous AndAlso result = 0 Then
source.Cancel()
Else
previous = result
End If
taskCtr += 1
taskTotal += result
Next
' Show result.
Console.WriteLine("Task {0} finished execution.", taskNo)
Console.WriteLine("Random numbers generated: {0:N0}", taskCtr)
Console.WriteLine("Sum of random numbers: {0:N2}", taskTotal)
Console.WriteLine("Random number mean: {0:N4}", taskTotal/taskCtr)
Console.WriteLine()
' Update overall totals.
SyncLock numericLock
totalCount += taskCtr
totalValue += taskTotal
End SyncLock
End Sub, token))
Next
Try
Task.WaitAll(tasks.ToArray())
Console.WriteLine()
Console.WriteLine("Total random numbers generated: {0:N0}", totalCount)
Console.WriteLine("Total sum of all random numbers: {0:N2}", totalValue)
Console.WriteLine("Random number mean: {0:N4}", totalValue/totalCount)
Catch e As AggregateException
For Each inner As Exception In e.InnerExceptions
Dim canc As TaskCanceledException = TryCast(inner, TaskCanceledException)
If canc IsNot Nothing Then
Console.WriteLine("Task #{0} cancelled.", canc.Task.Id)
Else
Console.WriteLine("Exception: {0}", inner.GetType().Name)
End If
Next
Finally
source.Dispose()
End Try
End Sub
End Module
' The example displays output like the following:
' Task 1 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 1,000,502.47
' Random number mean: 0.5003
'
' Task 0 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 1,000,445.63
' Random number mean: 0.5002
'
' Task 2 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 1,000,556.04
' Random number mean: 0.5003
'
' Task 3 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 1,000,178.87
' Random number mean: 0.5001
'
' Task 4 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,819.17
' Random number mean: 0.4999
'
' Task 5 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 1,000,190.58
' Random number mean: 0.5001
'
' Task 6 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,720.21
' Random number mean: 0.4999
'
' Task 7 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,000.96
' Random number mean: 0.4995
'
' Task 8 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,499.33
' Random number mean: 0.4997
'
' Task 9 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 1,000,193.25
' Random number mean: 0.5001
'
' Task 10 finished execution.
' Random numbers generated: 2,000,000
' Sum of random numbers: 999,960.82
' Random number mean: 0.5000
'
'
' Total random numbers generated: 22,000,000
' Total sum of all random numbers: 11,000,067.33
' Random number mean: 0.5000
Ela difere do primeiro exemplo das seguintes maneiras:
As variáveis a serem controladas pelo número de números aleatórios gerados e sua soma em cada tarefa são locais para a tarefa, portanto, não é necessário usar o ThreadStaticAttribute atributo .
O método estático Task.WaitAll é usado para garantir que o thread de main não seja concluído antes de todas as tarefas serem concluídas. Não há necessidade do CountdownEvent objeto .
A exceção resultante do cancelamento da tarefa é exibida no Task.WaitAll método . No exemplo anterior, ele é manipulado por cada thread.
Gerando diferentes tipos de números aleatórios
O gerador de números aleatórios fornece métodos que permitem gerar os seguintes tipos de números aleatórios:
Uma série de Byte valores. Você determina o número de valores de bytes passando uma matriz inicializada para o número de elementos que deseja que o método retorne ao NextBytes método . O exemplo a seguir gera 20 bytes.
using namespace System; void main() { Random^ rnd = gcnew Random(); array<Byte>^ bytes = gcnew array<Byte>(20); rnd->NextBytes(bytes); for (int ctr = 1; ctr <= bytes->Length; ctr++) { Console::Write("{0,3} ", bytes[ctr - 1]); if (ctr % 10 == 0) Console::WriteLine(); } } // The example displays output like the following: // 141 48 189 66 134 212 211 71 161 56 // 181 166 220 133 9 252 222 57 62 62
Random rnd = new Random(); Byte[] bytes = new Byte[20]; rnd.NextBytes(bytes); for (int ctr = 1; ctr <= bytes.Length; ctr++) { Console.Write("{0,3} ", bytes[ctr - 1]); if (ctr % 10 == 0) Console.WriteLine(); } // The example displays output like the following: // 141 48 189 66 134 212 211 71 161 56 // 181 166 220 133 9 252 222 57 62 62
let rnd = Random() let bytes = Array.zeroCreate 20 rnd.NextBytes bytes for i = 1 to bytes.Length do printf "%3i " bytes.[i - 1] if (i % 10 = 0) then printfn "" // The example displays output like the following: // 141 48 189 66 134 212 211 71 161 56 // 181 166 220 133 9 252 222 57 62 62
Module Example Public Sub Main() Dim rnd As New Random() Dim bytes(19) As Byte rnd.NextBytes(bytes) For ctr As Integer = 1 To bytes.Length Console.Write("{0,3} ", bytes(ctr - 1)) If ctr Mod 10 = 0 Then Console.WriteLine() Next End Sub End Module ' The example displays output like the following: ' 141 48 189 66 134 212 211 71 161 56 ' 181 166 220 133 9 252 222 57 62 62
Um único inteiro. Você pode escolher se deseja um inteiro de 0 a um valor máximo (Int32.MaxValue - 1) chamando o Next() método , um inteiro entre 0 e um valor específico chamando o Next(Int32) método ou um inteiro dentro de um intervalo de valores chamando o Next(Int32, Int32) método . Nas sobrecargas parametrizadas, o valor máximo especificado é exclusivo; ou seja, o número máximo real gerado é um menor que o valor especificado.
O exemplo a seguir chama o Next(Int32, Int32) método para gerar 10 números aleatórios entre -10 e 10. Observe que o segundo argumento para o método especifica o limite superior exclusivo do intervalo de valores aleatórios retornados pelo método . Em outras palavras, o maior inteiro que o método pode retornar é um menor que esse valor.
using namespace System; void main() { Random^ rnd = gcnew Random(); for (int ctr = 0; ctr < 10; ctr++) { Console::Write("{0,3} ", rnd->Next(-10, 11)); } } // The example displays output like the following: // 2 9 -3 2 4 -7 -3 -8 -8 5
Random rnd = new Random(); for (int ctr = 0; ctr < 10; ctr++) { Console.Write("{0,3} ", rnd.Next(-10, 11)); } // The example displays output like the following: // 2 9 -3 2 4 -7 -3 -8 -8 5
let rnd = Random() for i = 0 to 9 do printf "%3i " (rnd.Next(-10, 11)) // The example displays output like the following: // 2 9 -3 2 4 -7 -3 -8 -8 5
Module Example Public Sub Main() Dim rnd As New Random() For ctr As Integer = 0 To 9 Console.Write("{0,3} ", rnd.Next(-10, 11)) Next End Sub End Module ' The example displays output like the following: ' 2 9 -3 2 4 -7 -3 -8 -8 5
Um único valor de ponto flutuante de 0,0 para menos de 1,0 chamando o NextDouble método . O limite superior exclusivo do número aleatório retornado pelo método é 1, portanto, seu limite superior real é 0,999999999999999978. O exemplo a seguir gera 10 números aleatórios de ponto flutuante.
using namespace System; void main() { Random^ rnd = gcnew Random(); for (int ctr = 0; ctr < 10; ctr++) { Console::Write("{0,-19:R} ", rnd->NextDouble()); if ((ctr + 1) % 3 == 0) Console::WriteLine(); } } // The example displays output like the following: // 0.7911680553998649 0.0903414949264105 0.79776258291572455 // 0.615568345233597 0.652644504165577 0.84023809378977776 // 0.099662564741290441 0.91341467383942321 0.96018602045261581 // 0.74772306473354022
Random rnd = new Random(); for (int ctr = 0; ctr < 10; ctr++) { Console.Write("{0,-19:R} ", rnd.NextDouble()); if ((ctr + 1) % 3 == 0) Console.WriteLine(); } // The example displays output like the following: // 0.7911680553998649 0.0903414949264105 0.79776258291572455 // 0.615568345233597 0.652644504165577 0.84023809378977776 // 0.099662564741290441 0.91341467383942321 0.96018602045261581 // 0.74772306473354022
let rnd = Random() for i = 0 to 9 do printf $"{rnd.NextDouble(),-19:R} " if (i + 1) % 3 = 0 then printfn "" // The example displays output like the following: // 0.7911680553998649 0.0903414949264105 0.79776258291572455 // 0.615568345233597 0.652644504165577 0.84023809378977776 // 0.099662564741290441 0.91341467383942321 0.96018602045261581 // 0.74772306473354022
Module Example Public Sub Main() Dim rnd As New Random() For ctr As Integer = 0 To 9 Console.Write("{0,-19:R} ", rnd.NextDouble()) If (ctr + 1) Mod 3 = 0 Then Console.WriteLine() Next End Sub End Module ' The example displays output like the following: ' 0.7911680553998649 0.0903414949264105 0.79776258291572455 ' 0.615568345233597 0.652644504165577 0.84023809378977776 ' 0.099662564741290441 0.91341467383942321 0.96018602045261581 ' 0.74772306473354022
Importante
O Next(Int32, Int32) método permite que você especifique o intervalo do número aleatório retornado. No entanto, o maxValue
parâmetro , que especifica o número retornado do intervalo superior, é um valor exclusivo, não inclusivo. Isso significa que a chamada Next(0, 100)
de método retorna um valor entre 0 e 99 e não entre 0 e 100.
Você também pode usar a Random classe para tarefas como gerar valores T:System.Boolean aleatórios, gerar valores de ponto flutuante aleatórios com um intervalo diferente de 0 a 1, gerar inteiros aleatórios de 64 bits e recuperar aleatoriamente um elemento exclusivo de uma matriz ou coleção. Para essas e outras tarefas comuns, consulte a seção Como usar System.Random para...
Substituindo seu próprio algoritmo
Você pode implementar seu próprio gerador de número aleatório herdando da Random classe e fornecendo seu algoritmo de geração de número aleatório. Para fornecer seu próprio algoritmo, você deve substituir o Sample método , que implementa o algoritmo de geração de número aleatório. Você também deve substituir os Next()métodos , Next(Int32, Int32)e NextBytes para garantir que eles chamem o método substituído Sample . Você não precisa substituir os Next(Int32) métodos e NextDouble .
Para obter um exemplo que deriva da classe e modifica seu Random gerador de número pseudo-aleatório padrão, consulte a Sample página de referência.
Como você usa System.Random para...
As seções a seguir discutem e fornecem código de exemplo para algumas das maneiras que talvez você queira usar números aleatórios em seu aplicativo.
Recuperar a mesma sequência de valores aleatórios
Às vezes, você deseja gerar a mesma sequência de números aleatórios em cenários de teste de software e em jogos. O teste com a mesma sequência de números aleatórios permite detectar regressões e confirmar correções de bugs. Usar a mesma sequência de número aleatório em jogos permite que você reproduza jogos anteriores.
Você pode gerar a mesma sequência de números aleatórios fornecendo o mesmo valor de semente para o Random(Int32) construtor. O valor de semente fornece um valor inicial para o algoritmo de geração de número pseudo-aleatório. O exemplo a seguir usa 100100 como um valor de semente arbitrário para instanciar o Random objeto, exibe 20 valores aleatórios de ponto flutuante e persiste o valor de semente. Em seguida, ele restaura o valor de semente, cria uma instância de um novo gerador de número aleatório e exibe os mesmos 20 valores de ponto flutuante aleatórios. Observe que o exemplo pode produzir sequências diferentes de números aleatórios se executado em diferentes versões do .NET Framework.
using System;
using System.IO;
public class Example
{
public static void Main()
{
int seed = 100100;
ShowRandomNumbers(seed);
Console.WriteLine();
PersistSeed(seed);
DisplayNewRandomNumbers();
}
private static void ShowRandomNumbers(int seed)
{
Random rnd = new Random(seed);
for (int ctr = 0; ctr <= 20; ctr++)
Console.WriteLine(rnd.NextDouble());
}
private static void PersistSeed(int seed)
{
FileStream fs = new FileStream(@".\seed.dat", FileMode.Create);
BinaryWriter bin = new BinaryWriter(fs);
bin.Write(seed);
bin.Close();
}
private static void DisplayNewRandomNumbers()
{
FileStream fs = new FileStream(@".\seed.dat", FileMode.Open);
BinaryReader bin = new BinaryReader(fs);
int seed = bin.ReadInt32();
bin.Close();
Random rnd = new Random(seed);
for (int ctr = 0; ctr <= 20; ctr++)
Console.WriteLine(rnd.NextDouble());
}
}
// The example displays output like the following:
// 0.500193602172748
// 0.0209461245783354
// 0.465869495396442
// 0.195512794514891
// 0.928583675496552
// 0.729333720509584
// 0.381455668891527
// 0.0508996467343064
// 0.019261200921266
// 0.258578445417145
// 0.0177532266908107
// 0.983277184415272
// 0.483650274334313
// 0.0219647376900375
// 0.165910115077118
// 0.572085966622497
// 0.805291457942357
// 0.927985211335116
// 0.4228545699375
// 0.523320379910674
// 0.157783938645285
//
// 0.500193602172748
// 0.0209461245783354
// 0.465869495396442
// 0.195512794514891
// 0.928583675496552
// 0.729333720509584
// 0.381455668891527
// 0.0508996467343064
// 0.019261200921266
// 0.258578445417145
// 0.0177532266908107
// 0.983277184415272
// 0.483650274334313
// 0.0219647376900375
// 0.165910115077118
// 0.572085966622497
// 0.805291457942357
// 0.927985211335116
// 0.4228545699375
// 0.523320379910674
// 0.157783938645285
open System
open System.IO
let showRandomNumbers seed =
let rnd = Random seed
for _ = 0 to 20 do
printfn $"{rnd.NextDouble()}"
let persistSeed (seed: int) =
use bin = new BinaryWriter(new FileStream(@".\seed.dat", FileMode.Create))
bin.Write seed
let displayNewRandomNumbers () =
use bin = new BinaryReader(new FileStream(@".\seed.dat", FileMode.Open))
let seed = bin.ReadInt32()
let rnd = Random seed
for _ = 0 to 20 do
printfn $"{rnd.NextDouble()}"
let seed = 100100
showRandomNumbers seed
printfn ""
persistSeed seed
displayNewRandomNumbers ()
// The example displays output like the following:
// 0.500193602172748
// 0.0209461245783354
// 0.465869495396442
// 0.195512794514891
// 0.928583675496552
// 0.729333720509584
// 0.381455668891527
// 0.0508996467343064
// 0.019261200921266
// 0.258578445417145
// 0.0177532266908107
// 0.983277184415272
// 0.483650274334313
// 0.0219647376900375
// 0.165910115077118
// 0.572085966622497
// 0.805291457942357
// 0.927985211335116
// 0.4228545699375
// 0.523320379910674
// 0.157783938645285
//
// 0.500193602172748
// 0.0209461245783354
// 0.465869495396442
// 0.195512794514891
// 0.928583675496552
// 0.729333720509584
// 0.381455668891527
// 0.0508996467343064
// 0.019261200921266
// 0.258578445417145
// 0.0177532266908107
// 0.983277184415272
// 0.483650274334313
// 0.0219647376900375
// 0.165910115077118
// 0.572085966622497
// 0.805291457942357
// 0.927985211335116
// 0.4228545699375
// 0.523320379910674
// 0.157783938645285
using namespace System;
using namespace System::IO;
ref class RandomMethods
{
internal:
static void ShowRandomNumbers(int seed)
{
Random^ rnd = gcnew Random(seed);
for (int ctr = 0; ctr <= 20; ctr++)
Console::WriteLine(rnd->NextDouble());
}
static void PersistSeed(int seed)
{
FileStream^ fs = gcnew FileStream(".\\seed.dat", FileMode::Create);
BinaryWriter^ bin = gcnew BinaryWriter(fs);
bin->Write(seed);
bin->Close();
}
static void DisplayNewRandomNumbers()
{
FileStream^ fs = gcnew FileStream(".\\seed.dat", FileMode::Open);
BinaryReader^ bin = gcnew BinaryReader(fs);
int seed = bin->ReadInt32();
bin->Close();
Random^ rnd = gcnew Random(seed);
for (int ctr = 0; ctr <= 20; ctr++)
Console::WriteLine(rnd->NextDouble());
}
};
void main()
{
int seed = 100100;
RandomMethods::ShowRandomNumbers(seed);
Console::WriteLine();
RandomMethods::PersistSeed(seed);
RandomMethods::DisplayNewRandomNumbers();
}
// The example displays output like the following:
// 0.500193602172748
// 0.0209461245783354
// 0.465869495396442
// 0.195512794514891
// 0.928583675496552
// 0.729333720509584
// 0.381455668891527
// 0.0508996467343064
// 0.019261200921266
// 0.258578445417145
// 0.0177532266908107
// 0.983277184415272
// 0.483650274334313
// 0.0219647376900375
// 0.165910115077118
// 0.572085966622497
// 0.805291457942357
// 0.927985211335116
// 0.4228545699375
// 0.523320379910674
// 0.157783938645285
//
// 0.500193602172748
// 0.0209461245783354
// 0.465869495396442
// 0.195512794514891
// 0.928583675496552
// 0.729333720509584
// 0.381455668891527
// 0.0508996467343064
// 0.019261200921266
// 0.258578445417145
// 0.0177532266908107
// 0.983277184415272
// 0.483650274334313
// 0.0219647376900375
// 0.165910115077118
// 0.572085966622497
// 0.805291457942357
// 0.927985211335116
// 0.4228545699375
// 0.523320379910674
// 0.157783938645285
Imports System.IO
Module Example
Public Sub Main()
Dim seed As Integer = 100100
ShowRandomNumbers(seed)
Console.WriteLine()
PersistSeed(seed)
DisplayNewRandomNumbers()
End Sub
Private Sub ShowRandomNumbers(seed As Integer)
Dim rnd As New Random(seed)
For ctr As Integer = 0 To 20
Console.WriteLine(rnd.NextDouble())
Next
End Sub
Private Sub PersistSeed(seed As Integer)
Dim fs As New FileStream(".\seed.dat", FileMode.Create)
Dim bin As New BinaryWriter(fs)
bin.Write(seed)
bin.Close()
End Sub
Private Sub DisplayNewRandomNumbers()
Dim fs As New FileStream(".\seed.dat", FileMode.Open)
Dim bin As New BinaryReader(fs)
Dim seed As Integer = bin.ReadInt32()
bin.Close()
Dim rnd As New Random(seed)
For ctr As Integer = 0 To 20
Console.WriteLine(rnd.NextDouble())
Next
End Sub
End Module
' The example displays output like the following:
' 0.500193602172748
' 0.0209461245783354
' 0.465869495396442
' 0.195512794514891
' 0.928583675496552
' 0.729333720509584
' 0.381455668891527
' 0.0508996467343064
' 0.019261200921266
' 0.258578445417145
' 0.0177532266908107
' 0.983277184415272
' 0.483650274334313
' 0.0219647376900375
' 0.165910115077118
' 0.572085966622497
' 0.805291457942357
' 0.927985211335116
' 0.4228545699375
' 0.523320379910674
' 0.157783938645285
'
' 0.500193602172748
' 0.0209461245783354
' 0.465869495396442
' 0.195512794514891
' 0.928583675496552
' 0.729333720509584
' 0.381455668891527
' 0.0508996467343064
' 0.019261200921266
' 0.258578445417145
' 0.0177532266908107
' 0.983277184415272
' 0.483650274334313
' 0.0219647376900375
' 0.165910115077118
' 0.572085966622497
' 0.805291457942357
' 0.927985211335116
' 0.4228545699375
' 0.523320379910674
' 0.157783938645285
Recuperar sequências exclusivas de números aleatórios
Fornecer valores de semente diferentes para instâncias da Random classe faz com que cada gerador de número aleatório produza uma sequência diferente de valores. Você pode fornecer um valor de semente explicitamente chamando o Random(Int32) construtor ou implicitamente chamando o Random() construtor. A maioria dos desenvolvedores chama o construtor sem parâmetros, que usa o relógio do sistema. O exemplo a seguir usa essa abordagem para instanciar duas Random instâncias. Cada instância exibe uma série de 10 inteiros aleatórios.
using namespace System;
using namespace System::Threading;
void main()
{
Console::WriteLine("Instantiating two random number generators...");
Random^ rnd1 = gcnew Random();
Thread::Sleep(2000);
Random^ rnd2 = gcnew Random();
Console::WriteLine("\nThe first random number generator:");
for (int ctr = 1; ctr <= 10; ctr++)
Console::WriteLine(" {0}", rnd1->Next());
Console::WriteLine("\nThe second random number generator:");
for (int ctr = 1; ctr <= 10; ctr++)
Console::WriteLine(" {0}", rnd2->Next());
}
// The example displays output like the following:
// Instantiating two random number generators...
//
// The first random number generator:
// 643164361
// 1606571630
// 1725607587
// 2138048432
// 496874898
// 1969147632
// 2034533749
// 1840964542
// 412380298
// 47518930
//
// The second random number generator:
// 1251659083
// 1514185439
// 1465798544
// 517841554
// 1821920222
// 195154223
// 1538948391
// 1548375095
// 546062716
// 897797880
using System;
using System.Threading;
public class Example
{
public static void Main()
{
Console.WriteLine("Instantiating two random number generators...");
Random rnd1 = new Random();
Thread.Sleep(2000);
Random rnd2 = new Random();
Console.WriteLine("\nThe first random number generator:");
for (int ctr = 1; ctr <= 10; ctr++)
Console.WriteLine(" {0}", rnd1.Next());
Console.WriteLine("\nThe second random number generator:");
for (int ctr = 1; ctr <= 10; ctr++)
Console.WriteLine(" {0}", rnd2.Next());
}
}
// The example displays output like the following:
// Instantiating two random number generators...
//
// The first random number generator:
// 643164361
// 1606571630
// 1725607587
// 2138048432
// 496874898
// 1969147632
// 2034533749
// 1840964542
// 412380298
// 47518930
//
// The second random number generator:
// 1251659083
// 1514185439
// 1465798544
// 517841554
// 1821920222
// 195154223
// 1538948391
// 1548375095
// 546062716
// 897797880
open System
open System.Threading
printfn "Instantiating two random number generators..."
let rnd1 = Random()
Thread.Sleep 2000
let rnd2 = Random()
printfn "\nThe first random number generator:"
for _ = 1 to 10 do
printfn $" {rnd1.Next()}"
printfn "\nThe second random number generator:"
for _ = 1 to 10 do
printfn $" {rnd2.Next()}"
// The example displays output like the following:
// Instantiating two random number generators...
//
// The first random number generator:
// 643164361
// 1606571630
// 1725607587
// 2138048432
// 496874898
// 1969147632
// 2034533749
// 1840964542
// 412380298
// 47518930
//
// The second random number generator:
// 1251659083
// 1514185439
// 1465798544
// 517841554
// 1821920222
// 195154223
// 1538948391
// 1548375095
// 546062716
// 897797880
Imports System.Threading
Module Example
Public Sub Main()
Console.WriteLine("Instantiating two random number generators...")
Dim rnd1 As New Random()
Thread.Sleep(2000)
Dim rnd2 As New Random()
Console.WriteLine()
Console.WriteLine("The first random number generator:")
For ctr As Integer = 1 To 10
Console.WriteLine(" {0}", rnd1.Next())
Next
Console.WriteLine()
Console.WriteLine("The second random number generator:")
For ctr As Integer = 1 To 10
Console.WriteLine(" {0}", rnd2.Next())
Next
End Sub
End Module
' The example displays output like the following:
' Instantiating two random number generators...
'
' The first random number generator:
' 643164361
' 1606571630
' 1725607587
' 2138048432
' 496874898
' 1969147632
' 2034533749
' 1840964542
' 412380298
' 47518930
'
' The second random number generator:
' 1251659083
' 1514185439
' 1465798544
' 517841554
' 1821920222
' 195154223
' 1538948391
' 1548375095
' 546062716
' 897797880
No entanto, devido à resolução finita, o relógio do sistema não detecta diferenças de tempo inferiores a aproximadamente 15 milissegundos. Portanto, se o código chamar a Random() sobrecarga no .NET Framework para instanciar dois Random objetos sucessivamente, você poderá fornecer inadvertidamente os objetos com valores de semente idênticos. (A Random classe no .NET Core não tem essa limitação.) Para ver isso no exemplo anterior, comente a chamada de Thread.Sleep método e compile e execute o exemplo novamente.
Para evitar que isso aconteça, recomendamos que você instancie um único Random objeto em vez de vários. No entanto, como Random não é thread-safe, você deve usar algum dispositivo de sincronização se acessar uma Random instância de vários threads; para obter mais informações, consulte A classe Aleatória e a segurança de threads anteriormente neste tópico. Como alternativa, você pode usar um mecanismo de atraso, como o Sleep método usado no exemplo anterior, para garantir que as instanciações ocorram com mais de 15 milissegundos de diferença.
Recuperar inteiros em um intervalo especificado
Você pode recuperar inteiros em um intervalo especificado chamando o Next(Int32, Int32) método , que permite especificar o limite inferior e superior dos números que deseja que o gerador de números aleatórios retorne. O limite superior é um valor exclusivo, não inclusivo. Ou seja, ele não está incluído no intervalo de valores retornados pelo método . O exemplo a seguir usa esse método para gerar inteiros aleatórios entre -10 e 10. Observe que ele especifica 11, que é um valor maior que o desejado, como o valor do maxValue
argumento na chamada de método.
using namespace System;
void main()
{
Random^ rnd = gcnew Random();
for (int ctr = 1; ctr <= 15; ctr++) {
Console::Write("{0,3} ", rnd->Next(-10, 11));
if(ctr % 5 == 0) Console::WriteLine();
}
}
// The example displays output like the following:
// -2 -5 -1 -2 10
// -3 6 -4 -8 3
// -7 10 5 -2 4
Random rnd = new Random();
for (int ctr = 1; ctr <= 15; ctr++) {
Console.Write("{0,3} ", rnd.Next(-10, 11));
if(ctr % 5 == 0) Console.WriteLine();
}
// The example displays output like the following:
// -2 -5 -1 -2 10
// -3 6 -4 -8 3
// -7 10 5 -2 4
let rnd = Random()
for i = 1 to 15 do
printf "%3i " (rnd.Next(-10, 11))
if i % 5 = 0 then printfn ""
// The example displays output like the following:
// -2 -5 -1 -2 10
// -3 6 -4 -8 3
// -7 10 5 -2 4
Module Example
Public Sub Main()
Dim rnd As New Random()
For ctr As Integer = 1 To 15
Console.Write("{0,3} ", rnd.Next(-10, 11))
If ctr Mod 5 = 0 Then Console.WriteLine()
Next
End Sub
End Module
' The example displays output like the following:
' -2 -5 -1 -2 10
' -3 6 -4 -8 3
' -7 10 5 -2 4
Recuperar inteiros com um número especificado de dígitos
Você pode chamar o Next(Int32, Int32) método para recuperar números com um número especificado de dígitos. Por exemplo, para recuperar números com quatro dígitos (ou seja, números que variam de 1000 a 9999), você chama o Next(Int32, Int32) método com um minValue
valor de 1000 e um maxValue
valor de 10000, como mostra o exemplo a seguir.
using namespace System;
void main()
{
Random^ rnd = gcnew Random();
for (int ctr = 1; ctr <= 50; ctr++) {
Console::Write("{0,3} ", rnd->Next(1000, 10000));
if(ctr % 10 == 0) Console::WriteLine();
}
}
// The example displays output like the following:
// 9570 8979 5770 1606 3818 4735 8495 7196 7070 2313
// 5279 6577 5104 5734 4227 3373 7376 6007 8193 5540
// 7558 3934 3819 7392 1113 7191 6947 4963 9179 7907
// 3391 6667 7269 1838 7317 1981 5154 7377 3297 5320
// 9869 8694 2684 4949 2999 3019 2357 5211 9604 2593
Random rnd = new Random();
for (int ctr = 1; ctr <= 50; ctr++) {
Console.Write("{0,3} ", rnd.Next(1000, 10000));
if(ctr % 10 == 0) Console.WriteLine();
}
// The example displays output like the following:
// 9570 8979 5770 1606 3818 4735 8495 7196 7070 2313
// 5279 6577 5104 5734 4227 3373 7376 6007 8193 5540
// 7558 3934 3819 7392 1113 7191 6947 4963 9179 7907
// 3391 6667 7269 1838 7317 1981 5154 7377 3297 5320
// 9869 8694 2684 4949 2999 3019 2357 5211 9604 2593
let rnd = Random()
for i = 1 to 50 do
printf "%3i " (rnd.Next(1000, 10000))
if i % 10 = 0 then printfn ""
// The example displays output like the following:
// 9570 8979 5770 1606 3818 4735 8495 7196 7070 2313
// 5279 6577 5104 5734 4227 3373 7376 6007 8193 5540
// 7558 3934 3819 7392 1113 7191 6947 4963 9179 7907
// 3391 6667 7269 1838 7317 1981 5154 7377 3297 5320
// 9869 8694 2684 4949 2999 3019 2357 5211 9604 2593
Module Example
Public Sub Main()
Dim rnd As New Random()
For ctr As Integer = 1 To 50
Console.Write("{0,3} ", rnd.Next(1000, 10000))
If ctr Mod 10 = 0 Then Console.WriteLine()
Next
End Sub
End Module
' The example displays output like the following:
' 9570 8979 5770 1606 3818 4735 8495 7196 7070 2313
' 5279 6577 5104 5734 4227 3373 7376 6007 8193 5540
' 7558 3934 3819 7392 1113 7191 6947 4963 9179 7907
' 3391 6667 7269 1838 7317 1981 5154 7377 3297 5320
' 9869 8694 2684 4949 2999 3019 2357 5211 9604 2593
Recuperar valores de ponto flutuante em um intervalo especificado
O NextDouble método retorna valores de ponto flutuante aleatórios que variam de 0 a menos de 1. No entanto, muitas vezes, você desejará gerar valores aleatórios em algum outro intervalo.
Se o intervalo entre os valores mínimo e máximo desejado for 1, você poderá adicionar a diferença entre o intervalo inicial desejado e 0 ao número retornado pelo NextDouble método . O exemplo a seguir faz isso para gerar 10 números aleatórios entre -1 e 0.
using namespace System;
void main()
{
Random^ rnd = gcnew Random();
for (int ctr = 1; ctr <= 10; ctr++)
Console::WriteLine(rnd->NextDouble() - 1);
}
// The example displays output like the following:
// -0.930412760437658
// -0.164699016215605
// -0.9851692803135
// -0.43468508843085
// -0.177202483255976
// -0.776813320245972
// -0.0713201854710096
// -0.0912875561468711
// -0.540621722368813
// -0.232211863730201
Random rnd = new Random();
for (int ctr = 1; ctr <= 10; ctr++)
Console.WriteLine(rnd.NextDouble() - 1);
// The example displays output like the following:
// -0.930412760437658
// -0.164699016215605
// -0.9851692803135
// -0.43468508843085
// -0.177202483255976
// -0.776813320245972
// -0.0713201854710096
// -0.0912875561468711
// -0.540621722368813
// -0.232211863730201
let rnd = Random()
for _ = 1 to 10 do
printfn "%O" (rnd.NextDouble() - 1.0)
// The example displays output like the following:
// -0.930412760437658
// -0.164699016215605
// -0.9851692803135
// -0.43468508843085
// -0.177202483255976
// -0.776813320245972
// -0.0713201854710096
// -0.0912875561468711
// -0.540621722368813
// -0.232211863730201
Module Example
Public Sub Main()
Dim rnd As New Random()
For ctr As Integer = 1 To 10
Console.WriteLine(rnd.NextDouble() - 1)
Next
End Sub
End Module
' The example displays output like the following:
' -0.930412760437658
' -0.164699016215605
' -0.9851692803135
' -0.43468508843085
' -0.177202483255976
' -0.776813320245972
' -0.0713201854710096
' -0.0912875561468711
' -0.540621722368813
' -0.232211863730201
Para gerar números aleatórios de ponto flutuante cujo limite inferior é 0, mas o limite superior é maior que 1 (ou, no caso de números negativos, cujo limite inferior é menor que -1 e o limite superior é 0), multiplique o número aleatório pelo limite diferente de zero. O exemplo a seguir faz isso para gerar 20 milhões de números de ponto flutuante aleatórios que variam de 0 a Int64.MaxValue. No também exibe a distribuição dos valores aleatórios gerados pelo método .
using namespace System;
void main()
{
const Int64 ONE_TENTH = 922337203685477581;
Random^ rnd = gcnew Random();
double number;
array<int>^ count = gcnew array<int>(10);
// Generate 20 million integer values between.
for (int ctr = 1; ctr <= 20000000; ctr++) {
number = rnd->NextDouble() * Int64::MaxValue;
// Categorize random numbers into 10 groups.
int value = (int) (number / ONE_TENTH);
count[value]++;
}
// Display breakdown by range.
Console::WriteLine("{0,28} {1,32} {2,7}\n", "Range", "Count", "Pct.");
for (int ctr = 0; ctr <= 9; ctr++)
Console::WriteLine("{0,25:N0}-{1,25:N0} {2,8:N0} {3,7:P2}", ctr * ONE_TENTH,
ctr < 9 ? ctr * ONE_TENTH + ONE_TENTH - 1 : Int64::MaxValue,
count[ctr], count[ctr]/20000000.0);
}
// The example displays output like the following:
// Range Count Pct.
//
// 0- 922,337,203,685,477,580 1,996,148 9.98 %
// 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 %
// 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 %
// 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 %
// 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 %
// 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 %
// 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 %
// 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 %
// 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 %
// 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 %
const long ONE_TENTH = 922337203685477581;
Random rnd = new Random();
double number;
int[] count = new int[10];
// Generate 20 million integer values between.
for (int ctr = 1; ctr <= 20000000; ctr++) {
number = rnd.NextDouble() * Int64.MaxValue;
// Categorize random numbers into 10 groups.
count[(int) (number / ONE_TENTH)]++;
}
// Display breakdown by range.
Console.WriteLine("{0,28} {1,32} {2,7}\n", "Range", "Count", "Pct.");
for (int ctr = 0; ctr <= 9; ctr++)
Console.WriteLine("{0,25:N0}-{1,25:N0} {2,8:N0} {3,7:P2}", ctr * ONE_TENTH,
ctr < 9 ? ctr * ONE_TENTH + ONE_TENTH - 1 : Int64.MaxValue,
count[ctr], count[ctr]/20000000.0);
// The example displays output like the following:
// Range Count Pct.
//
// 0- 922,337,203,685,477,580 1,996,148 9.98 %
// 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 %
// 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 %
// 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 %
// 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 %
// 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 %
// 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 %
// 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 %
// 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 %
// 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 %
[<Literal>]
let ONE_TENTH = 922337203685477581L
let rnd = Random()
// Generate 20 million random integers.
let count =
Array.init 20000000 (fun _ -> rnd.NextDouble() * (float Int64.MaxValue) )
|> Array.countBy (fun x -> x / (float ONE_TENTH) |> int ) // Categorize into 10 groups and count them.
|> Array.map snd
// Display breakdown by range.
printfn "%28s %32s %7s\n" "Range" "Count" "Pct."
for i = 0 to 9 do
let r1 = int64 i * ONE_TENTH
let r2 = if i < 9 then r1 + ONE_TENTH - 1L else Int64.MaxValue
printfn $"{r1,25:N0}-{r2,25:N0} {count.[i],8:N0} {float count.[i] / 20000000.0,7:P2}"
// The example displays output like the following:
// Range Count Pct.
//
// 0- 922,337,203,685,477,580 1,996,148 9.98 %
// 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 %
// 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 %
// 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 %
// 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 %
// 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 %
// 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 %
// 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 %
// 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 %
// 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 %
Module Example
Public Sub Main()
Const ONE_TENTH As Long = 922337203685477581
Dim rnd As New Random()
Dim number As Long
Dim count(9) As Integer
' Generate 20 million integer values.
For ctr As Integer = 1 To 20000000
number = CLng(rnd.NextDouble() * Int64.MaxValue)
' Categorize random numbers.
count(CInt(number \ ONE_TENTH)) += 1
Next
' Display breakdown by range.
Console.WriteLine("{0,28} {1,32} {2,7}", "Range", "Count", "Pct.")
Console.WriteLine()
For ctr As Integer = 0 To 9
Console.WriteLine("{0,25:N0}-{1,25:N0} {2,8:N0} {3,7:P2}", ctr * ONE_TENTH,
If(ctr < 9, ctr * ONE_TENTH + ONE_TENTH - 1, Int64.MaxValue),
count(ctr), count(ctr)/20000000)
Next
End Sub
End Module
' The example displays output like the following:
' Range Count Pct.
'
' 0- 922,337,203,685,477,580 1,996,148 9.98 %
' 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 %
' 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 %
' 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 %
' 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 %
' 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 %
' 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 %
' 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 %
' 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 %
' 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 %
Para gerar números aleatórios de ponto flutuante entre dois valores arbitrários, como o Next(Int32, Int32) método faz para inteiros, use a seguinte fórmula:
Random.NextDouble() * (maxValue - minValue) + minValue
O exemplo a seguir gera 1 milhão de números aleatórios que variam de 10,0 a 11,0 e exibe sua distribuição.
using namespace System;
void main()
{
Random^ rnd = gcnew Random();
int lowerBound = 10;
int upperBound = 11;
array<int>^ range = gcnew array<int>(10);
for (int ctr = 1; ctr <= 1000000; ctr++) {
Double value = rnd->NextDouble() * (upperBound - lowerBound) + lowerBound;
range[(int) Math::Truncate((value - lowerBound) * 10)]++;
}
for (int ctr = 0; ctr <= 9; ctr++) {
Double lowerRange = 10 + ctr * .1;
Console::WriteLine("{0:N1} to {1:N1}: {2,8:N0} ({3,7:P2})",
lowerRange, lowerRange + .1, range[ctr],
range[ctr] / 1000000.0);
}
}
// The example displays output like the following:
// 10.0 to 10.1: 99,929 ( 9.99 %)
// 10.1 to 10.2: 100,189 (10.02 %)
// 10.2 to 10.3: 99,384 ( 9.94 %)
// 10.3 to 10.4: 100,240 (10.02 %)
// 10.4 to 10.5: 99,397 ( 9.94 %)
// 10.5 to 10.6: 100,580 (10.06 %)
// 10.6 to 10.7: 100,293 (10.03 %)
// 10.7 to 10.8: 100,135 (10.01 %)
// 10.8 to 10.9: 99,905 ( 9.99 %)
// 10.9 to 11.0: 99,948 ( 9.99 %)
Random rnd = new Random();
int lowerBound = 10;
int upperBound = 11;
int[] range = new int[10];
for (int ctr = 1; ctr <= 1000000; ctr++) {
Double value = rnd.NextDouble() * (upperBound - lowerBound) + lowerBound;
range[(int) Math.Truncate((value - lowerBound) * 10)]++;
}
for (int ctr = 0; ctr <= 9; ctr++) {
Double lowerRange = 10 + ctr * .1;
Console.WriteLine("{0:N1} to {1:N1}: {2,8:N0} ({3,7:P2})",
lowerRange, lowerRange + .1, range[ctr],
range[ctr] / 1000000.0);
}
// The example displays output like the following:
// 10.0 to 10.1: 99,929 ( 9.99 %)
// 10.1 to 10.2: 100,189 (10.02 %)
// 10.2 to 10.3: 99,384 ( 9.94 %)
// 10.3 to 10.4: 100,240 (10.02 %)
// 10.4 to 10.5: 99,397 ( 9.94 %)
// 10.5 to 10.6: 100,580 (10.06 %)
// 10.6 to 10.7: 100,293 (10.03 %)
// 10.7 to 10.8: 100,135 (10.01 %)
// 10.8 to 10.9: 99,905 ( 9.99 %)
// 10.9 to 11.0: 99,948 ( 9.99 %)
let rnd = Random()
let lowerBound = 10.0
let upperBound = 11.0
let range =
Array.init 1000000 (fun _ -> rnd.NextDouble() * (upperBound - lowerBound) + lowerBound)
|> Array.countBy (fun x -> Math.Truncate((x - lowerBound) * 10.0) |> int)
|> Array.map snd
for i = 0 to 9 do
let lowerRange = 10.0 + float i * 0.1
printfn $"{lowerRange:N1} to {lowerRange + 0.1:N1}: {range.[i],8:N0} ({float range.[i] / 1000000.0,6:P2})"
// The example displays output like the following:
// 10.0 to 10.1: 99,929 ( 9.99 %)
// 10.1 to 10.2: 100,189 (10.02 %)
// 10.2 to 10.3: 99,384 ( 9.94 %)
// 10.3 to 10.4: 100,240 (10.02 %)
// 10.4 to 10.5: 99,397 ( 9.94 %)
// 10.5 to 10.6: 100,580 (10.06 %)
// 10.6 to 10.7: 100,293 (10.03 %)
// 10.7 to 10.8: 100,135 (10.01 %)
// 10.8 to 10.9: 99,905 ( 9.99 %)
// 10.9 to 11.0: 99,948 ( 9.99 %)
Module Example
Public Sub Main()
Dim rnd As New Random()
Dim lowerBound As Integer = 10
Dim upperBound As Integer = 11
Dim range(9) As Integer
For ctr As Integer = 1 To 1000000
Dim value As Double = rnd.NextDouble() * (upperBound - lowerBound) + lowerBound
range(CInt(Math.Truncate((value - lowerBound) * 10))) += 1
Next
For ctr As Integer = 0 To 9
Dim lowerRange As Double = 10 + ctr * .1
Console.WriteLine("{0:N1} to {1:N1}: {2,8:N0} ({3,7:P2})",
lowerRange, lowerRange + .1, range(ctr),
range(ctr) / 1000000.0)
Next
End Sub
End Module
' The example displays output like the following:
' 10.0 to 10.1: 99,929 ( 9.99 %)
' 10.1 to 10.2: 100,189 (10.02 %)
' 10.2 to 10.3: 99,384 ( 9.94 %)
' 10.3 to 10.4: 100,240 (10.02 %)
' 10.4 to 10.5: 99,397 ( 9.94 %)
' 10.5 to 10.6: 100,580 (10.06 %)
' 10.6 to 10.7: 100,293 (10.03 %)
' 10.7 to 10.8: 100,135 (10.01 %)
' 10.8 to 10.9: 99,905 ( 9.99 %)
' 10.9 to 11.0: 99,948 ( 9.99 %)
Gerar valores boolianos aleatórios
A Random classe não fornece métodos que geram Boolean valores. No entanto, você pode definir sua própria classe ou método para fazer isso. O exemplo a seguir define uma classe, BooleanGenerator
, com um único método, NextBoolean
. A BooleanGenerator
classe armazena um Random objeto como uma variável privada. O NextBoolean
método chama o Random.Next(Int32, Int32) método e passa o resultado para o Convert.ToBoolean(Int32) método . Observe que 2 é usado como o argumento para especificar o limite superior do número aleatório. Como esse é um valor exclusivo, a chamada de método retorna 0 ou 1.
using namespace System;
public ref class BooleanGenerator
{
private:
Random^ rnd;
public:
BooleanGenerator()
{
rnd = gcnew Random();
}
bool NextBoolean()
{
return Convert::ToBoolean(rnd->Next(0, 2));
}
};
void main()
{
// Instantiate the Boolean generator.
BooleanGenerator^ boolGen = gcnew BooleanGenerator();
int totalTrue = 0, totalFalse = 0;
// Generate 1,0000 random Booleans, and keep a running total.
for (int ctr = 0; ctr < 1000000; ctr++) {
bool value = boolGen->NextBoolean();
if (value)
totalTrue++;
else
totalFalse++;
}
Console::WriteLine("Number of true values: {0,7:N0} ({1:P3})",
totalTrue,
((double) totalTrue)/(totalTrue + totalFalse));
Console::WriteLine("Number of false values: {0,7:N0} ({1:P3})",
totalFalse,
((double) totalFalse)/(totalTrue + totalFalse));
}
// The example displays output like the following:
// Number of true values: 500,004 (50.000 %)
// Number of false values: 499,996 (50.000 %)
using System;
public class Example
{
public static void Main()
{
// Instantiate the Boolean generator.
BooleanGenerator boolGen = new BooleanGenerator();
int totalTrue = 0, totalFalse = 0;
// Generate 1,0000 random Booleans, and keep a running total.
for (int ctr = 0; ctr < 1000000; ctr++) {
bool value = boolGen.NextBoolean();
if (value)
totalTrue++;
else
totalFalse++;
}
Console.WriteLine("Number of true values: {0,7:N0} ({1:P3})",
totalTrue,
((double) totalTrue)/(totalTrue + totalFalse));
Console.WriteLine("Number of false values: {0,7:N0} ({1:P3})",
totalFalse,
((double) totalFalse)/(totalTrue + totalFalse));
}
}
public class BooleanGenerator
{
Random rnd;
public BooleanGenerator()
{
rnd = new Random();
}
public bool NextBoolean()
{
return rnd.Next(0, 2) == 1;
}
}
// The example displays output like the following:
// Number of true values: 500,004 (50.000 %)
// Number of false values: 499,996 (50.000 %)
open System
type BooleanGenerator() =
let rnd = Random()
member _.NextBoolean() =
rnd.Next(0, 2) = 1
let boolGen = BooleanGenerator()
let mutable totalTrue, totalFalse = 0, 0
for _ = 1 to 1000000 do
let value = boolGen.NextBoolean()
if value then
totalTrue <- totalTrue + 1
else
totalFalse <- totalFalse + 1
printfn $"Number of true values: {totalTrue,7:N0} ({(double totalTrue) / double (totalTrue + totalFalse):P3})"
printfn $"Number of false values: {totalFalse,7:N0} ({(double totalFalse) / double (totalTrue + totalFalse):P3})"
// The example displays output like the following:
// Number of true values: 500,004 (50.000 %)
// Number of false values: 499,996 (50.000 %)
Module Example
Public Sub Main()
' Instantiate the Boolean generator.
Dim boolGen As New BooleanGenerator()
Dim totalTrue, totalFalse As Integer
' Generate 1,0000 random Booleans, and keep a running total.
For ctr As Integer = 0 To 9999999
Dim value As Boolean = boolGen.NextBoolean()
If value Then
totalTrue += 1
Else
totalFalse += 1
End If
Next
Console.WriteLine("Number of true values: {0,7:N0} ({1:P3})",
totalTrue,
totalTrue/(totalTrue + totalFalse))
Console.WriteLine("Number of false values: {0,7:N0} ({1:P3})",
totalFalse,
totalFalse/(totalTrue + totalFalse))
End Sub
End Module
Public Class BooleanGenerator
Dim rnd As Random
Public Sub New()
rnd = New Random()
End Sub
Public Function NextBoolean() As Boolean
Return Convert.ToBoolean(rnd.Next(0, 2))
End Function
End Class
' The example displays the following output:
' Number of true values: 500,004 (50.000 %)
' Number of false values: 499,996 (50.000 %)
Em vez de criar uma classe separada para gerar valores aleatórios Boolean , o exemplo poderia simplesmente ter definido um único método. Nesse caso, no entanto, o Random objeto deveria ter sido definido como uma variável de nível de classe para evitar a instanciação de uma nova Random instância em cada chamada de método. No Visual Basic, a instância Aleatória pode ser definida como uma variável estática no NextBoolean
método . O exemplo a seguir fornece uma implementação.
using namespace System;
ref class Example
{
private:
static Random^ rnd = gcnew Random();
public:
static void Execute()
{
int totalTrue = 0, totalFalse = 0;
// Generate 1,0000 random Booleans, and keep a running total.
for (int ctr = 0; ctr < 1000000; ctr++) {
bool value = NextBoolean();
if (value)
totalTrue++;
else
totalFalse++;
}
Console::WriteLine("Number of true values: {0,7:N0} ({1:P3})",
totalTrue,
((double) totalTrue)/(totalTrue + totalFalse));
Console::WriteLine("Number of false values: {0,7:N0} ({1:P3})",
totalFalse,
((double) totalFalse)/(totalTrue + totalFalse));
}
static bool NextBoolean()
{
return Convert::ToBoolean(rnd->Next(0, 2));
}
};
void main()
{
Example::Execute();
}
// The example displays output like the following:
// Number of true values: 499,777 (49.978 %)
// Number of false values: 500,223 (50.022 %)
Random rnd = new Random();
int totalTrue = 0, totalFalse = 0;
// Generate 1,000,000 random Booleans, and keep a running total.
for (int ctr = 0; ctr < 1000000; ctr++) {
bool value = NextBoolean();
if (value)
totalTrue++;
else
totalFalse++;
}
Console.WriteLine("Number of true values: {0,7:N0} ({1:P3})",
totalTrue,
((double) totalTrue)/(totalTrue + totalFalse));
Console.WriteLine("Number of false values: {0,7:N0} ({1:P3})",
totalFalse,
((double) totalFalse)/(totalTrue + totalFalse));
bool NextBoolean()
{
return rnd.Next(0, 2) == 1;
}
// The example displays output like the following:
// Number of true values: 499,777 (49.978 %)
// Number of false values: 500,223 (50.022 %)
let rnd = Random()
let nextBool () =
rnd.Next(0, 2) = 1
let mutable totalTrue, totalFalse = 0, 0
for _ = 1 to 1000000 do
let value = nextBool ()
if value then
totalTrue <- totalTrue + 1
else
totalFalse <- totalFalse + 1
printfn $"Number of true values: {totalTrue,7:N0} ({(double totalTrue) / double (totalTrue + totalFalse):P3})"
printfn $"Number of false values: {totalFalse,7:N0} ({(double totalFalse) / double (totalTrue + totalFalse):P3})"
// The example displays output like the following:
// Number of true values: 499,777 (49.978 %)
// Number of false values: 500,223 (50.022 %)
Module Example
Public Sub Main()
Dim totalTrue, totalFalse As Integer
' Generate 1,0000 random Booleans, and keep a running total.
For ctr As Integer = 0 To 9999999
Dim value As Boolean = NextBoolean()
If value Then
totalTrue += 1
Else
totalFalse += 1
End If
Next
Console.WriteLine("Number of true values: {0,7:N0} ({1:P3})",
totalTrue,
totalTrue/(totalTrue + totalFalse))
Console.WriteLine("Number of false values: {0,7:N0} ({1:P3})",
totalFalse,
totalFalse/(totalTrue + totalFalse))
End Sub
Public Function NextBoolean() As Boolean
Static rnd As New Random()
Return Convert.ToBoolean(rnd.Next(0, 2))
End Function
End Module
' The example displays the following output:
' Number of true values: 499,777 (49.978 %)
' Number of false values: 500,223 (50.022 %)
Gerar inteiros aleatórios de 64 bits
As sobrecargas do Next método retornam inteiros de 32 bits. No entanto, em alguns casos, talvez você queira trabalhar com inteiros de 64 bits. Você pode fazer isso da seguinte maneira:
Chame o NextDouble método para recuperar um valor de ponto flutuante de precisão dupla.
Multiplique esse valor por Int64.MaxValue.
O exemplo a seguir usa essa técnica para gerar 20 milhões de inteiros longos aleatórios e categorizá-los em 10 grupos iguais. Em seguida, ele avalia a distribuição dos números aleatórios contando o número em cada grupo de 0 para Int64.MaxValue. Como mostra a saída do exemplo, os números são distribuídos mais ou menos igualmente por meio do intervalo de um inteiro longo.
using namespace System;
void main()
{
const Int64 ONE_TENTH = 922337203685477581;
Random^ rnd = gcnew Random();
Int64 number;
array<int>^ count = gcnew array<int>(10);
// Generate 20 million long integers.
for (int ctr = 1; ctr <= 20000000; ctr++) {
number = (Int64) (rnd->NextDouble() * Int64::MaxValue);
// Categorize random numbers.
count[(int) (number / ONE_TENTH)]++;
}
// Display breakdown by range.
Console::WriteLine("{0,28} {1,32} {2,7}\n", "Range", "Count", "Pct.");
for (int ctr = 0; ctr <= 9; ctr++)
Console::WriteLine("{0,25:N0}-{1,25:N0} {2,8:N0} {3,7:P2}", ctr * ONE_TENTH,
ctr < 9 ? ctr * ONE_TENTH + ONE_TENTH - 1 : Int64::MaxValue,
count[ctr], count[ctr]/20000000.0);
}
// The example displays output like the following:
// Range Count Pct.
//
// 0- 922,337,203,685,477,580 1,996,148 9.98 %
// 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 %
// 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 %
// 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 %
// 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 %
// 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 %
// 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 %
// 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 %
// 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 %
// 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 %
const long ONE_TENTH = 922337203685477581;
Random rnd = new Random();
long number;
int[] count = new int[10];
// Generate 20 million long integers.
for (int ctr = 1; ctr <= 20000000; ctr++) {
number = (long) (rnd.NextDouble() * Int64.MaxValue);
// Categorize random numbers.
count[(int) (number / ONE_TENTH)]++;
}
// Display breakdown by range.
Console.WriteLine("{0,28} {1,32} {2,7}\n", "Range", "Count", "Pct.");
for (int ctr = 0; ctr <= 9; ctr++)
Console.WriteLine("{0,25:N0}-{1,25:N0} {2,8:N0} {3,7:P2}", ctr * ONE_TENTH,
ctr < 9 ? ctr * ONE_TENTH + ONE_TENTH - 1 : Int64.MaxValue,
count[ctr], count[ctr]/20000000.0);
// The example displays output like the following:
// Range Count Pct.
//
// 0- 922,337,203,685,477,580 1,996,148 9.98 %
// 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 %
// 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 %
// 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 %
// 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 %
// 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 %
// 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 %
// 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 %
// 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 %
// 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 %
[<Literal>]
let ONE_TENTH = 922337203685477581L
let rnd = Random()
let count =
// Generate 20 million random long integers.
Array.init 20000000 (fun _ -> rnd.NextDouble() * (float Int64.MaxValue) |> int64 )
|> Array.countBy (fun x -> x / ONE_TENTH) // Categorize and count random numbers.
|> Array.map snd
// Display breakdown by range.
printfn "%28s %32s %7s\n" "Range" "Count" "Pct."
for i = 0 to 9 do
let r1 = int64 i * ONE_TENTH
let r2 = if i < 9 then r1 + ONE_TENTH - 1L else Int64.MaxValue
printfn $"{r1,25:N0}-{r2,25:N0} {count.[i],8:N0} {float count.[i] / 20000000.0,7:P2}"
// The example displays output like the following:
// Range Count Pct.
//
// 0- 922,337,203,685,477,580 1,996,148 9.98 %
// 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 %
// 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 %
// 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 %
// 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 %
// 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 %
// 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 %
// 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 %
// 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 %
// 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 %
Module Example
Public Sub Main()
Const ONE_TENTH As Long = 922337203685477581
Dim rnd As New Random()
Dim number As Long
Dim count(9) As Integer
' Generate 20 million long integers.
For ctr As Integer = 1 To 20000000
number = CLng(rnd.NextDouble() * Int64.MaxValue)
' Categorize random numbers.
count(CInt(number \ ONE_TENTH)) += 1
Next
' Display breakdown by range.
Console.WriteLine("{0,28} {1,32} {2,7}", "Range", "Count", "Pct.")
Console.WriteLine()
For ctr As Integer = 0 To 9
Console.WriteLine("{0,25:N0}-{1,25:N0} {2,8:N0} {3,7:P2}", ctr * ONE_TENTH,
If(ctr < 9, ctr * ONE_TENTH + ONE_TENTH - 1, Int64.MaxValue),
count(ctr), count(ctr)/20000000)
Next
End Sub
End Module
' The example displays output like the following:
' Range Count Pct.
'
' 0- 922,337,203,685,477,580 1,996,148 9.98 %
' 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 %
' 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 %
' 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 %
' 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 %
' 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 %
' 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 %
' 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 %
' 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 %
' 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 %
Uma técnica alternativa que usa a manipulação de bits não gera números verdadeiramente aleatórios. Essa técnica chama Next() para gerar dois inteiros, desloca um por 32 bits à esquerda e os ORs juntos. Essa técnica tem duas limitações:
Como o bit 31 é o bit de sinal, o valor no bit 31 do inteiro longo resultante é sempre 0. Isso pode ser resolvido gerando um 0 ou 1 aleatório, deslocando-o para a esquerda de 31 bits e ORing com o inteiro longo aleatório original.
Mais seriamente, como a probabilidade de que o valor retornado por Next() será 0, haverá poucos se algum número aleatório no intervalo 0x0-0x00000000FFFFFFFF.
Recuperar bytes em um intervalo especificado
As sobrecargas do Next método permitem que você especifique o intervalo de números aleatórios, mas o NextBytes método não. O exemplo a seguir implementa um NextBytes
método que permite especificar o intervalo dos bytes retornados. Ele define uma Random2
classe que deriva de Random e sobrecarrega seu NextBytes
método.
using namespace System;
ref class Random2 : Random
{
public:
Random2()
{}
Random2(int seed) : Random(seed)
{}
void NextBytes(array<Byte>^ bytes, Byte minValue, Byte maxValue)
{
for (int ctr = bytes->GetLowerBound(0); ctr <= bytes->GetUpperBound(0); ctr++)
bytes[ctr] = (Byte) Next(minValue, maxValue);
}
};
void main()
{
Random2^ rnd = gcnew Random2();
array<Byte>^ bytes = gcnew array<Byte>(10000);
array<int>^ total = gcnew array<int>(101);
rnd->NextBytes(bytes, 0, 101);
// Calculate how many of each value we have.
for each (Byte value in bytes)
total[value]++;
// Display the results.
for (int ctr = 0; ctr < total->Length; ctr++) {
Console::Write("{0,3}: {1,-3} ", ctr, total[ctr]);
if ((ctr + 1) % 5 == 0) Console::WriteLine();
}
}
// The example displays output like the following:
// 0: 115 1: 119 2: 92 3: 98 4: 92
// 5: 102 6: 103 7: 84 8: 93 9: 116
// 10: 91 11: 98 12: 106 13: 91 14: 92
// 15: 101 16: 100 17: 96 18: 97 19: 100
// 20: 101 21: 106 22: 112 23: 82 24: 85
// 25: 102 26: 107 27: 98 28: 106 29: 102
// 30: 109 31: 108 32: 94 33: 101 34: 107
// 35: 101 36: 86 37: 100 38: 101 39: 102
// 40: 113 41: 95 42: 96 43: 89 44: 99
// 45: 81 46: 89 47: 105 48: 100 49: 85
// 50: 103 51: 103 52: 93 53: 89 54: 91
// 55: 97 56: 105 57: 97 58: 110 59: 86
// 60: 116 61: 94 62: 117 63: 98 64: 110
// 65: 93 66: 102 67: 100 68: 105 69: 83
// 70: 81 71: 97 72: 85 73: 70 74: 98
// 75: 100 76: 110 77: 114 78: 83 79: 90
// 80: 96 81: 112 82: 102 83: 102 84: 99
// 85: 81 86: 100 87: 93 88: 99 89: 118
// 90: 95 91: 124 92: 108 93: 96 94: 104
// 95: 106 96: 99 97: 99 98: 92 99: 99
// 100: 108
using System;
public class Example
{
public static void Main()
{
Random2 rnd = new Random2();
Byte[] bytes = new Byte[10000];
int[] total = new int[101];
rnd.NextBytes(bytes, 0, 101);
// Calculate how many of each value we have.
foreach (var value in bytes)
total[value]++;
// Display the results.
for (int ctr = 0; ctr < total.Length; ctr++) {
Console.Write("{0,3}: {1,-3} ", ctr, total[ctr]);
if ((ctr + 1) % 5 == 0) Console.WriteLine();
}
}
}
public class Random2 : Random
{
public Random2() : base()
{}
public Random2(int seed) : base(seed)
{}
public void NextBytes(byte[] bytes, byte minValue, byte maxValue)
{
for (int ctr = bytes.GetLowerBound(0); ctr <= bytes.GetUpperBound(0); ctr++)
bytes[ctr] = (byte) Next(minValue, maxValue);
}
}
// The example displays output like the following:
// 0: 115 1: 119 2: 92 3: 98 4: 92
// 5: 102 6: 103 7: 84 8: 93 9: 116
// 10: 91 11: 98 12: 106 13: 91 14: 92
// 15: 101 16: 100 17: 96 18: 97 19: 100
// 20: 101 21: 106 22: 112 23: 82 24: 85
// 25: 102 26: 107 27: 98 28: 106 29: 102
// 30: 109 31: 108 32: 94 33: 101 34: 107
// 35: 101 36: 86 37: 100 38: 101 39: 102
// 40: 113 41: 95 42: 96 43: 89 44: 99
// 45: 81 46: 89 47: 105 48: 100 49: 85
// 50: 103 51: 103 52: 93 53: 89 54: 91
// 55: 97 56: 105 57: 97 58: 110 59: 86
// 60: 116 61: 94 62: 117 63: 98 64: 110
// 65: 93 66: 102 67: 100 68: 105 69: 83
// 70: 81 71: 97 72: 85 73: 70 74: 98
// 75: 100 76: 110 77: 114 78: 83 79: 90
// 80: 96 81: 112 82: 102 83: 102 84: 99
// 85: 81 86: 100 87: 93 88: 99 89: 118
// 90: 95 91: 124 92: 108 93: 96 94: 104
// 95: 106 96: 99 97: 99 98: 92 99: 99
// 100: 108
open System
type Random2() =
inherit Random()
member this.NextBytes(bytes: byte[], minValue: byte, maxValue: byte) =
for i=bytes.GetLowerBound(0) to bytes.GetUpperBound(0) do
bytes.[i] <- this.Next(int minValue, int maxValue) |> byte
let rnd = Random2()
let bytes = Array.zeroCreate 10000
let total = Array.zeroCreate 101
rnd.NextBytes(bytes, 0uy, 101uy)
// Calculate how many of each value we have.
for v in bytes do
total.[int v] <- total.[int v] + 1
// Display the results.
for i = 0 to total.Length - 1 do
printf "%3i: %-3i " i total.[i]
if (i + 1) % 5 = 0 then printfn ""
// The example displays output like the following:
// 0: 115 1: 119 2: 92 3: 98 4: 92
// 5: 102 6: 103 7: 84 8: 93 9: 116
// 10: 91 11: 98 12: 106 13: 91 14: 92
// 15: 101 16: 100 17: 96 18: 97 19: 100
// 20: 101 21: 106 22: 112 23: 82 24: 85
// 25: 102 26: 107 27: 98 28: 106 29: 102
// 30: 109 31: 108 32: 94 33: 101 34: 107
// 35: 101 36: 86 37: 100 38: 101 39: 102
// 40: 113 41: 95 42: 96 43: 89 44: 99
// 45: 81 46: 89 47: 105 48: 100 49: 85
// 50: 103 51: 103 52: 93 53: 89 54: 91
// 55: 97 56: 105 57: 97 58: 110 59: 86
// 60: 116 61: 94 62: 117 63: 98 64: 110
// 65: 93 66: 102 67: 100 68: 105 69: 83
// 70: 81 71: 97 72: 85 73: 70 74: 98
// 75: 100 76: 110 77: 114 78: 83 79: 90
// 80: 96 81: 112 82: 102 83: 102 84: 99
// 85: 81 86: 100 87: 93 88: 99 89: 118
// 90: 95 91: 124 92: 108 93: 96 94: 104
// 95: 106 96: 99 97: 99 98: 92 99: 99
// 100: 108
Module Example
Public Sub Main()
Dim rnd As New Random2()
Dim bytes(9999) As Byte
Dim total(100) As Integer
rnd.NextBytes(bytes, 0, 101)
' Calculate how many of each value we have.
For Each value In bytes
total(value) += 1
Next
' Display the results.
For ctr As Integer = 0 To total.Length - 1
Console.Write("{0,3}: {1,-3} ", ctr, total(ctr))
If (ctr + 1) Mod 5 = 0 Then Console.WriteLine()
Next
End Sub
End Module
Public Class Random2 : Inherits Random
Public Sub New()
MyBase.New()
End Sub
Public Sub New(seed As Integer)
MyBase.New(seed)
End Sub
Public Overloads Sub NextBytes(bytes() As Byte,
minValue As Byte, maxValue As Byte)
For ctr As Integer = bytes.GetLowerbound(0) To bytes.GetUpperBound(0)
bytes(ctr) = CByte(MyBase.Next(minValue, maxValue))
Next
End Sub
End Class
' The example displays output like the following:
' 0: 115 1: 119 2: 92 3: 98 4: 92
' 5: 102 6: 103 7: 84 8: 93 9: 116
' 10: 91 11: 98 12: 106 13: 91 14: 92
' 15: 101 16: 100 17: 96 18: 97 19: 100
' 20: 101 21: 106 22: 112 23: 82 24: 85
' 25: 102 26: 107 27: 98 28: 106 29: 102
' 30: 109 31: 108 32: 94 33: 101 34: 107
' 35: 101 36: 86 37: 100 38: 101 39: 102
' 40: 113 41: 95 42: 96 43: 89 44: 99
' 45: 81 46: 89 47: 105 48: 100 49: 85
' 50: 103 51: 103 52: 93 53: 89 54: 91
' 55: 97 56: 105 57: 97 58: 110 59: 86
' 60: 116 61: 94 62: 117 63: 98 64: 110
' 65: 93 66: 102 67: 100 68: 105 69: 83
' 70: 81 71: 97 72: 85 73: 70 74: 98
' 75: 100 76: 110 77: 114 78: 83 79: 90
' 80: 96 81: 112 82: 102 83: 102 84: 99
' 85: 81 86: 100 87: 93 88: 99 89: 118
' 90: 95 91: 124 92: 108 93: 96 94: 104
' 95: 106 96: 99 97: 99 98: 92 99: 99
' 100: 108
O NextBytes(Byte[], Byte, Byte)
método encapsula uma chamada para o Next(Int32, Int32) método e especifica o valor mínimo e um maior que o valor máximo (nesse caso, 0 e 101) que desejamos retornar na matriz de bytes. Como temos certeza de que os valores inteiros retornados pelo Next método estão dentro do intervalo do tipo de Byte dados, podemos convertê-los com segurança (em C# e F#) ou convertê-los (no Visual Basic) de inteiros em bytes.
Recuperar um elemento de uma matriz ou coleção aleatoriamente
Números aleatórios geralmente servem como índices para recuperar valores de matrizes ou coleções. Para recuperar um valor de índice aleatório, você pode chamar o Next(Int32, Int32) método e usar o limite inferior da matriz como o valor de seu minValue
argumento e um maior que o limite superior da matriz como o valor de seu maxValue
argumento. Para uma matriz baseada em zero, isso é equivalente à sua Length propriedade ou um maior que o valor retornado pelo Array.GetUpperBound método . O exemplo a seguir recupera aleatoriamente o nome de uma cidade no Estados Unidos de uma matriz de cidades.
using namespace System;
void main()
{
array<String^>^ cities = { "Atlanta", "Boston", "Chicago", "Detroit",
"Fort Wayne", "Greensboro", "Honolulu", "Indianapolis",
"Jersey City", "Kansas City", "Los Angeles",
"Milwaukee", "New York", "Omaha", "Philadelphia",
"Raleigh", "San Francisco", "Tulsa", "Washington" };
Random^ rnd = gcnew Random();
int index = rnd->Next(0, cities->Length);
Console::WriteLine("Today's city of the day: {0}",
cities[index]);
}
// The example displays output like the following:
// Today's city of the day: Honolulu
String[] cities = { "Atlanta", "Boston", "Chicago", "Detroit",
"Fort Wayne", "Greensboro", "Honolulu", "Indianapolis",
"Jersey City", "Kansas City", "Los Angeles",
"Milwaukee", "New York", "Omaha", "Philadelphia",
"Raleigh", "San Francisco", "Tulsa", "Washington" };
Random rnd = new Random();
int index = rnd.Next(0, cities.Length);
Console.WriteLine("Today's city of the day: {0}",
cities[index]);
// The example displays output like the following:
// Today's city of the day: Honolulu
let cities =
[| "Atlanta"; "Boston"; "Chicago"; "Detroit";
"Fort Wayne"; "Greensboro"; "Honolulu"; "Indianapolis";
"Jersey City"; "Kansas City"; "Los Angeles";
"Milwaukee"; "New York"; "Omaha"; "Philadelphia";
"Raleigh"; "San Francisco"; "Tulsa"; "Washington" |]
let rnd = Random()
let index = rnd.Next(0,cities.Length)
printfn "Today's city of the day: %s" cities.[index]
// The example displays output like the following:
// Today's city of the day: Honolulu
Module Example
Public Sub Main()
Dim cities() As String = { "Atlanta", "Boston", "Chicago", "Detroit",
"Fort Wayne", "Greensboro", "Honolulu", "Indianapolis",
"Jersey City", "Kansas City", "Los Angeles",
"Milwaukee", "New York", "Omaha", "Philadelphia",
"Raleigh", "San Francisco", "Tulsa", "Washington" }
Dim rnd As New Random()
Dim index As Integer = rnd.Next(0, cities.Length)
Console.WriteLine("Today's city of the day: {0}",
cities(index))
End Sub
End Module
' The example displays output like the following:
' Today's city of the day: Honolulu
Recuperar um elemento exclusivo de uma matriz ou coleção
Um gerador de números aleatórios sempre pode retornar valores duplicados. À medida que o intervalo de números se torna menor ou o número de valores gerados se torna maior, a probabilidade de duplicatas aumenta. Se os valores aleatórios precisarem ser exclusivos, mais números serão gerados para compensar as duplicatas, resultando em um desempenho cada vez mais ruim.
Há várias técnicas para lidar com esse cenário. Uma solução comum é criar uma matriz ou coleção que contenha os valores a serem recuperados e uma matriz paralela que contenha números aleatórios de ponto flutuante. A segunda matriz é preenchida com números aleatórios no momento em que a primeira matriz é criada e o Array.Sort(Array, Array) método é usado para classificar a primeira matriz usando os valores na matriz paralela.
Por exemplo, se você estiver desenvolvendo um jogo do Paciência, deseja garantir que cada cartão seja usado apenas uma vez. Em vez de gerar números aleatórios para recuperar um cartão e acompanhar se esse cartão já foi tratado, você pode criar uma matriz paralela de números aleatórios que podem ser usados para classificar o baralho. Depois que o baralho for classificado, seu aplicativo poderá manter um ponteiro para indicar o índice do próximo cartão no baralho.
O exemplo a seguir ilustra esta abordagem. Ele define uma Card
classe que representa uma cartão de jogo e uma Dealer
classe que lida com um baralho de cartas embaralhadas. O Dealer
construtor de classe popula duas matrizes: uma deck
matriz que tem escopo de classe e que representa todos os cartões no baralho; e uma matriz local order
que tem o mesmo número de elementos que a deck
matriz e é populada com valores gerados Double aleatoriamente. Em Array.Sort(Array, Array) seguida, o método é chamado para classificar a deck
matriz com base nos valores na order
matriz.
using namespace System;
public enum class Suit { Hearts, Diamonds, Spades, Clubs };
public enum class FaceValue { Ace = 1, Two, Three, Four, Five, Six,
Seven, Eight, Nine, Ten, Jack, Queen,
King };
// A class that represents an individual card in a playing deck.
ref class Card
{
public:
Suit Suit;
FaceValue FaceValue;
String^ ToString() override
{
return String::Format("{0:F} of {1:F}", this->FaceValue, this->Suit);
}
};
ref class Dealer
{
private:
Random^ rnd;
// A deck of cards, without Jokers.
array<Card^>^ deck = gcnew array<Card^>(52);
// Parallel array for sorting cards.
array<Double>^ order = gcnew array<Double>(52);
// A pointer to the next card to deal.
int ptr = 0;
// A flag to indicate the deck is used.
bool mustReshuffle = false;
public:
Dealer()
{
rnd = gcnew Random();
// Initialize the deck.
int deckCtr = 0;
for each (auto suit in Enum::GetValues(Suit::typeid)) {
for each (FaceValue faceValue in Enum::GetValues(FaceValue::typeid)) {
Card^ card = gcnew Card();
card->Suit = (Suit) suit;
card->FaceValue = (FaceValue) faceValue;
deck[deckCtr] = card;
deckCtr++;
}
}
for (int ctr = 0; ctr < order->Length; ctr++)
order[ctr] = rnd->NextDouble();
Array::Sort(order, deck);
}
array<Card^>^ Deal(int numberToDeal)
{
if (mustReshuffle) {
Console::WriteLine("There are no cards left in the deck");
return nullptr;
}
array<Card^>^ cardsDealt = gcnew array<Card^>(numberToDeal);
for (int ctr = 0; ctr < numberToDeal; ctr++) {
cardsDealt[ctr] = deck[ptr];
ptr++;
if (ptr == deck->Length)
mustReshuffle = true;
if (mustReshuffle & ctr < numberToDeal - 1) {
Console::WriteLine("Can only deal the {0} cards remaining on the deck.",
ctr + 1);
return cardsDealt;
}
}
return cardsDealt;
}
};
void ShowCards(array<Card^>^ cards)
{
for each (Card^ card in cards)
if (card != nullptr)
Console::WriteLine("{0} of {1}", card->FaceValue, card->Suit);
};
void main()
{
Dealer^ dealer = gcnew Dealer();
ShowCards(dealer->Deal(20));
}
// The example displays output like the following:
// Six of Diamonds
// King of Clubs
// Eight of Clubs
// Seven of Clubs
// Queen of Clubs
// King of Hearts
// Three of Spades
// Ace of Clubs
// Four of Hearts
// Three of Diamonds
// Nine of Diamonds
// Two of Hearts
// Ace of Hearts
// Three of Hearts
// Four of Spades
// Eight of Hearts
// Queen of Diamonds
// Two of Clubs
// Four of Diamonds
// Jack of Hearts
using System;
// A class that represents an individual card in a playing deck.
public class Card
{
public Suit Suit;
public FaceValue FaceValue;
public override String ToString()
{
return String.Format("{0:F} of {1:F}", this.FaceValue, this.Suit);
}
}
public enum Suit { Hearts, Diamonds, Spades, Clubs };
public enum FaceValue { Ace = 1, Two, Three, Four, Five, Six,
Seven, Eight, Nine, Ten, Jack, Queen,
King };
public class Dealer
{
Random rnd;
// A deck of cards, without Jokers.
Card[] deck = new Card[52];
// Parallel array for sorting cards.
Double[] order = new Double[52];
// A pointer to the next card to deal.
int ptr = 0;
// A flag to indicate the deck is used.
bool mustReshuffle = false;
public Dealer()
{
rnd = new Random();
// Initialize the deck.
int deckCtr = 0;
foreach (var suit in Enum.GetValues(typeof(Suit))) {
foreach (var faceValue in Enum.GetValues(typeof(FaceValue))) {
Card card = new Card();
card.Suit = (Suit) suit;
card.FaceValue = (FaceValue) faceValue;
deck[deckCtr] = card;
deckCtr++;
}
}
for (int ctr = 0; ctr < order.Length; ctr++)
order[ctr] = rnd.NextDouble();
Array.Sort(order, deck);
}
public Card[] Deal(int numberToDeal)
{
if (mustReshuffle) {
Console.WriteLine("There are no cards left in the deck");
return null;
}
Card[] cardsDealt = new Card[numberToDeal];
for (int ctr = 0; ctr < numberToDeal; ctr++) {
cardsDealt[ctr] = deck[ptr];
ptr++;
if (ptr == deck.Length)
mustReshuffle = true;
if (mustReshuffle & ctr < numberToDeal - 1) {
Console.WriteLine("Can only deal the {0} cards remaining on the deck.",
ctr + 1);
return cardsDealt;
}
}
return cardsDealt;
}
}
public class Example
{
public static void Main()
{
Dealer dealer = new Dealer();
ShowCards(dealer.Deal(20));
}
private static void ShowCards(Card[] cards)
{
foreach (var card in cards)
if (card != null)
Console.WriteLine("{0} of {1}", card.FaceValue, card.Suit);
}
}
// The example displays output like the following:
// Six of Diamonds
// King of Clubs
// Eight of Clubs
// Seven of Clubs
// Queen of Clubs
// King of Hearts
// Three of Spades
// Ace of Clubs
// Four of Hearts
// Three of Diamonds
// Nine of Diamonds
// Two of Hearts
// Ace of Hearts
// Three of Hearts
// Four of Spades
// Eight of Hearts
// Queen of Diamonds
// Two of Clubs
// Four of Diamonds
// Jack of Hearts
open System
type Suit =
| Clubs
| Diamonds
| Hearts
| Spades
type Face =
| Ace | Two | Three
| Four | Five | Six
| Seven | Eight | Nine
| Ten | Jack | Queen | King
type Card = { Face: Face; Suit: Suit }
let suits = [ Clubs; Diamonds; Hearts; Spades ]
let faces = [ Ace; Two; Three; Four; Five; Six; Seven; Eight; Nine; Ten; Jack; Queen; King ]
type Dealer() =
let rnd = Random()
let mutable pos = 0
// Parallel array for sorting cards.
let order = Array.init (suits.Length * faces.Length) (fun _ -> rnd.NextDouble() )
// A deck of cards, without Jokers.
let deck = [|
for s in suits do
for f in faces do
{ Face = f; Suit = s } |]
// Shuffle the deck.
do Array.Sort(order, deck)
// Deal a number of cards from the deck, return None if failed
member _.Deal(numberToDeal) : Card [] option =
if numberToDeal = 0 || pos = deck.Length then
printfn "There are no cards left in the deck"
None
else
let cards = deck.[pos .. numberToDeal + pos - 1]
if numberToDeal > deck.Length - pos then
printfn "Can only deal the %i cards remaining on the deck." (deck.Length - pos)
pos <- min (pos + numberToDeal) deck.Length
Some cards
let showCards cards =
for card in cards do
printfn $"{card.Face} of {card.Suit}"
let dealer = Dealer()
dealer.Deal 20
|> Option.iter showCards
// The example displays output like the following:
// Six of Diamonds
// King of Clubs
// Eight of Clubs
// Seven of Clubs
// Queen of Clubs
// King of Hearts
// Three of Spades
// Ace of Clubs
// Four of Hearts
// Three of Diamonds
// Nine of Diamonds
// Two of Hearts
// Ace of Hearts
// Three of Hearts
// Four of Spades
// Eight of Hearts
// Queen of Diamonds
// Two of Clubs
// Four of Diamonds
// Jack of Hearts
' A class that represents an individual card in a playing deck.
Public Class Card
Public Suit As Suit
Public FaceValue As FaceValue
Public Overrides Function ToString() As String
Return String.Format("{0:F} of {1:F}", Me.FaceValue, Me.Suit)
End Function
End Class
Public Enum Suit As Integer
Hearts = 0
Diamonds = 1
Spades = 2
Clubs = 3
End Enum
Public Enum FaceValue As Integer
Ace = 1
Two = 2
Three = 3
Four = 4
Five = 5
Six = 6
Seven = 7
Eight = 8
Nine = 9
Ten = 10
Jack = 11
Queen = 12
King = 13
End Enum
Public Class Dealer
Dim rnd As Random
' A deck of cards, without Jokers.
Dim deck(51) As Card
' Parallel array for sorting cards.
Dim order(51) As Double
' A pointer to the next card to deal.
Dim ptr As Integer = 0
' A flag to indicate the deck is used.
Dim mustReshuffle As Boolean
Public Sub New()
rnd = New Random()
' Initialize the deck.
Dim deckCtr As Integer = 0
For Each Suit In [Enum].GetValues(GetType(Suit))
For Each faceValue In [Enum].GetValues(GetType(FaceValue))
Dim card As New Card()
card.Suit = CType(Suit, Suit)
card.FaceValue = CType(faceValue, FaceValue)
deck(deckCtr) = card
deckCtr += 1
Next
Next
For ctr As Integer = 0 To order.Length - 1
order(ctr) = rnd.NextDouble()
Next
Array.Sort(order, deck)
End Sub
Public Function Deal(numberToDeal As Integer) As Card()
If mustReshuffle Then
Console.WriteLine("There are no cards left in the deck")
Return Nothing
End If
Dim cardsDealt(numberToDeal - 1) As Card
For ctr As Integer = 0 To numberToDeal - 1
cardsDealt(ctr) = deck(ptr)
ptr += 1
If ptr = deck.Length Then
mustReshuffle = True
End If
If mustReshuffle And ctr < numberToDeal - 1
Console.WriteLine("Can only deal the {0} cards remaining on the deck.",
ctr + 1)
Return cardsDealt
End If
Next
Return cardsDealt
End Function
End Class
Public Module Example
Public Sub Main()
Dim dealer As New Dealer()
ShowCards(dealer.Deal(20))
End Sub
Private Sub ShowCards(cards() As Card)
For Each card In cards
If card IsNot Nothing Then _
Console.WriteLine("{0} of {1}", card.FaceValue, card.Suit)
Next
End Sub
End Module
' The example displays output like the following:
' Six of Diamonds
' King of Clubs
' Eight of Clubs
' Seven of Clubs
' Queen of Clubs
' King of Hearts
' Three of Spades
' Ace of Clubs
' Four of Hearts
' Three of Diamonds
' Nine of Diamonds
' Two of Hearts
' Ace of Hearts
' Three of Hearts
' Four of Spades
' Eight of Hearts
' Queen of Diamonds
' Two of Clubs
' Four of Diamonds
' Jack of Hearts
Notas aos Herdeiros
No .NET Framework 1.0 e 1.1, uma implementação mínima de uma classe derivada da Random substituição necessária do Sample() método para definir um algoritmo novo ou modificado para gerar números aleatórios. A classe derivada poderia então contar com a implementação da classe base dos Next()métodos , Next(Int32), Next(Int32, Int32), NextBytes(Byte[])e NextDouble() para chamar a implementação de classe derivada do Sample() método .
No .NET Framework 2.0 e posterior, o comportamento dos Next()métodos , Next(Int32, Int32)e NextBytes(Byte[]) foi alterado para que esses métodos não necessariamente chamem a implementação de classe derivada do Sample() método . Como resultado, as classes derivadas desse Random destino para o .NET Framework 2.0 e posterior também devem substituir esses três métodos.
Notas aos Chamadores
Não há garantia de que a implementação do gerador de número aleatório na Random classe permaneça a mesma nas versões principais do .NET Framework. Como resultado, você não deve assumir que a mesma semente resultará na mesma sequência pseudo-aleatória em versões diferentes do .NET Framework.
Construtores
Random() |
Inicializa uma nova instância da classe Random usando um valor de semente padrão. |
Random(Int32) |
Inicializa uma nova instância da classe Random, usando o valor de semente especificado. |
Propriedades
Shared |
Fornece uma instância thread-safe Random que pode ser usada simultaneamente de qualquer thread. |
Métodos
Equals(Object) |
Determina se o objeto especificado é igual ao objeto atual. (Herdado de Object) |
GetHashCode() |
Serve como a função de hash padrão. (Herdado de Object) |
GetItems<T>(ReadOnlySpan<T>, Int32) |
Cria uma matriz preenchida com itens escolhidos aleatoriamente do conjunto de opções fornecido. |
GetItems<T>(ReadOnlySpan<T>, Span<T>) |
Preenche os elementos de um intervalo especificado com itens escolhidos aleatoriamente do conjunto de opções fornecido. |
GetItems<T>(T[], Int32) |
Cria uma matriz preenchida com itens escolhidos aleatoriamente do conjunto de opções fornecido. |
GetType() |
Obtém o Type da instância atual. (Herdado de Object) |
MemberwiseClone() |
Cria uma cópia superficial do Object atual. (Herdado de Object) |
Next() |
Retorna um inteiro aleatório não negativo. |
Next(Int32) |
Retorna um número inteiro aleatório não negativo menor que o máximo especificado. |
Next(Int32, Int32) |
Retorna um inteiro aleatório que está dentro do intervalo especificado. |
NextBytes(Byte[]) |
Preenche os elementos de uma matriz de bytes especificada com números aleatórios. |
NextBytes(Span<Byte>) |
Preenche os elementos de um intervalo de bytes especificado com números aleatórios. |
NextDouble() |
Retorna um número de ponto flutuante aleatório maior ou igual a 0,0 e menor que 1.0. |
NextInt64() |
Retorna um inteiro aleatório não negativo. |
NextInt64(Int64) |
Retorna um número inteiro aleatório não negativo menor que o máximo especificado. |
NextInt64(Int64, Int64) |
Retorna um inteiro aleatório que está dentro do intervalo especificado. |
NextSingle() |
Retorna um número de ponto flutuante aleatório maior ou igual a 0,0 e menor que 1.0. |
Sample() |
Retorna um número de ponto flutuante aleatório entre 0.0 e 1.0. |
Shuffle<T>(Span<T>) |
Executa uma ordem aleatória in-loco de um intervalo. |
Shuffle<T>(T[]) |
Executa uma ordem aleatória in-loco de uma matriz. |
ToString() |
Retorna uma cadeia de caracteres que representa o objeto atual. (Herdado de Object) |