Jawaban:
The Random
kelas digunakan untuk membuat nomor acak. (Tentu saja semu-acak.).
Contoh:
Random rnd = new Random();
int month = rnd.Next(1, 13); // creates a number between 1 and 12
int dice = rnd.Next(1, 7); // creates a number between 1 and 6
int card = rnd.Next(52); // creates a number between 0 and 51
Jika Anda ingin membuat lebih dari satu angka acak, Anda harus menyimpan Random
instance dan menggunakannya kembali. Jika Anda membuat instance baru terlalu dekat dalam waktu, mereka akan menghasilkan seri angka acak yang sama dengan generator acak diunggulkan dari jam sistem.
rnd
sebagai static
dan / atau mengaturnya sekali saja saat menginisialisasi kode.
Random
...
Random
luar sana untuk membuat keacakan Anda lebih kuat: ericlippert.com/2019/02/04/fixing-random-part-2 dan codeblog.jonskeet.uk/2009/11/04/revisiting -Randomness .
Pertanyaannya terlihat sangat sederhana tetapi jawabannya agak rumit. Jika Anda melihat hampir semua orang menyarankan untuk menggunakan kelas Acak dan beberapa menyarankan untuk menggunakan kelas kripto RNG. Tetapi kemudian kapan harus memilih apa.
Untuk itu kita perlu terlebih dahulu memahami istilah KEANDALAN dan filosofi di baliknya.
Saya mendorong Anda untuk menonton video ini yang mendalami filosofi RANDOMNESS menggunakan C # https://www.youtube.com/watch?v=tCYxc-2-3fY
Hal pertama marilah kita memahami filosofi KEANDALAN. Ketika kami memberi tahu seseorang untuk memilih antara MERAH, HIJAU dan KUNING apa yang terjadi secara internal. Apa yang membuat seseorang memilih MERAH atau KUNING atau HIJAU?
Beberapa pemikiran awal masuk ke pikiran orang yang memutuskan pilihannya, itu bisa menjadi warna favorit, warna keberuntungan dan sebagainya. Dengan kata lain beberapa pemicu awal yang kita sebut dalam RANDOM sebagai SEED. SEED ini adalah titik awal, pemicu yang menghasutnya untuk memilih nilai RANDOM.
Sekarang jika SEED mudah ditebak maka angka-angka acak semacam itu disebut sebagai PSEUDO dan ketika sebuah seed sulit ditebak, angka-angka acak itu disebut angka acak SECURED .
Misalnya seseorang memilih warna tergantung pada kombinasi cuaca dan suara maka akan sulit untuk menebak benih awal.
Sekarang izinkan saya membuat pernyataan penting: -
* "Random" kelas menghasilkan hanya nomor acak PSEUDO dan untuk menghasilkan nomor acak SECURE kita perlu menggunakan kelas "RNGCryptoServiceProvider".
Kelas acak mengambil nilai seed dari jam CPU Anda yang sangat mudah diprediksi. Jadi dengan kata lain kelas ACAK dari C # menghasilkan angka acak semu, di bawah ini adalah kode yang sama.
** Catatan: ** .NET Core 2.0.0+
menggunakan seed berbeda pada konstruktor tanpa parameter: alih-alih jam CPU yang digunakan Guid.NewGuid().GetHashCode()
.
var random = new Random();
int randomnumber = random.Next()
Sementara RNGCryptoServiceProvider
kelas menggunakan entropi OS untuk menghasilkan benih. Entropi OS adalah nilai acak yang dihasilkan menggunakan suara, klik mouse, dan pengaturan waktu keyboard, suhu termal, dll. Di bawah ini adalah kode yang sama.
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[5];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
}
Untuk memahami entropi OS, lihat video ini dari pukul 14:30 https://www.youtube.com/watch?v=tCYxc-2-3fY di mana logika entropi OS dijelaskan. Jadi dengan kata-kata sederhana RNG Crypto menghasilkan angka acak AMAN.
RandomNumberGenerator.Create()
alih-alih memanggil konstruktor RNGCryptoServiceProvider
karena tidak tersedia di semua platform.
Setiap kali Anda melakukan Acak baru () diinisialisasi. Ini berarti bahwa dalam loop ketat Anda mendapatkan nilai yang sama banyak kali. Anda harus menyimpan satu instance Acak dan terus menggunakan Next pada instance yang sama.
//Function to get random number
private static readonly Random getrandom = new Random();
public static int GetRandomNumber(int min, int max)
{
lock(getrandom) // synchronize
{
return getrandom.Next(min, max);
}
}
Random
objek yang sama . Pada kedua kasus saya mendapat nomor acak yang sama. Dengan pendekatan dari Pankaj itu tidak terjadi. Mungkin ini acak , tapi saya ragu sekarang. Saya meminta nomor acak di detik yang sama dari utas berbeda.
Waspadalah yang new Random()
diunggulkan di cap waktu saat ini.
Jika Anda ingin menghasilkan hanya satu nomor, Anda dapat menggunakan:
new Random().Next( int.MinValue, int.MaxValue )
Untuk informasi lebih lanjut, lihat kelas Acak , namun harap dicatat:
Namun, karena jam memiliki resolusi hingga, menggunakan konstruktor tanpa parameter untuk membuat objek Acak yang berbeda secara berurutan membuat generator angka acak yang menghasilkan urutan identik dari nomor acak
Jadi jangan gunakan kode ini untuk menghasilkan serangkaian angka acak.
new Random()
dalam satu lingkaran adalah poin penting.
Saya ingin menambahkan versi yang aman secara kriptografis:
Kelas RNGCryptoServiceProvider ( MSDN atau dotnetperls )
Ini mengimplementasikan IDisposable.
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] randomNumber = new byte[4];//4 for int32
rng.GetBytes(randomNumber);
int value = BitConverter.ToInt32(randomNumber, 0);
}
Anda bisa menggunakan metode StaticRandom Jon Skeet di dalam perpustakaan kelas MiscUtil yang ia buat untuk nomor pseudo-acak.
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
Saya sudah mencoba semua solusi ini kecuali jawaban COBOL ... lol
Tidak ada solusi yang cukup baik. Saya membutuhkan tebasan dalam loop cepat untuk int dan saya mendapatkan banyak nilai duplikat bahkan dalam rentang yang sangat luas. Setelah puas dengan hasil acak yang terlalu lama, saya memutuskan untuk akhirnya mengatasi masalah ini untuk selamanya.
Ini semua tentang benih.
Saya membuat bilangan bulat acak dengan mem-parsing non-digit dari Guid, lalu saya menggunakannya untuk membuat instance kelas acak saya.
public int GenerateRandom(int min, int max)
{
var seed = Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), @"\d+").Value);
return new Random(seed).Next(min, max);
}
Pembaruan : Pembibitan tidak diperlukan jika Anda membuat instance kelas Acak satu kali. Jadi akan lebih baik untuk membuat kelas statis dan memanggil metode itu.
public static class IntUtil
{
private static Random random;
private static void Init()
{
if (random == null) random = new Random();
}
public static int Random(int min, int max)
{
Init();
return random.Next(min, max);
}
}
Maka Anda dapat menggunakan kelas statis seperti itu ..
for(var i = 0; i < 1000; i++)
{
int randomNumber = IntUtil.Random(1,100);
Console.WriteLine(randomNumber);
}
Saya akui saya lebih suka pendekatan ini.
Angka-angka yang dihasilkan oleh Random
kelas inbuilt (System.Random) menghasilkan angka acak semu.
Jika Anda menginginkan angka acak yang benar, yang terdekat yang bisa kami dapatkan adalah "secure Pseudo Random Generator" yang dapat dihasilkan dengan menggunakan kelas-kelas Kriptografi dalam C # seperti RNGCryptoServiceProvider
.
Meski begitu, jika Anda masih membutuhkan bilangan acak sejati, Anda harus menggunakan sumber eksternal seperti perangkat yang menghitung peluruhan radioaktif sebagai seed untuk generator bilangan acak. Karena, menurut definisi, angka apa pun yang dihasilkan dengan cara algoritmik murni tidak dapat benar-benar acak.
buat objek acak
Random rand = new Random();
dan gunakan itu
int randomNumber = rand.Next(min, max);
Anda tidak perlu menginisialisasi new Random()
setiap kali Anda membutuhkan nomor acak, mulai satu acak lalu gunakan sebanyak yang Anda butuhkan dalam satu lingkaran atau apa pun
new Random()
menggunakan kutu saat ini sebagai benih. Ketika Anda instantiate beberapa instance dalam milidetik yang sama (sebagai lawan dari centang), maka Anda akan mendapatkan nilai yang sama dikembalikan.
Jawaban yang dimodifikasi dari sini .
Jika Anda memiliki akses ke CPU yang kompatibel dengan Intel Secure Key, Anda dapat menghasilkan bilangan dan string acak nyata menggunakan perpustakaan ini: https://github.com/JebteK/RdRand dan https://www.rdrand.com/
Cukup unduh versi terbaru dari sini , termasuk Jebtek.RdRand dan tambahkan pernyataan menggunakan untuk itu. Kemudian, yang perlu Anda lakukan adalah ini:
// Check to see if this is a compatible CPU
bool isAvailable = RdRandom.GeneratorAvailable();
// Generate 10 random characters
string key = RdRandom.GenerateKey(10);
// Generate 64 random characters, useful for API keys
string apiKey = RdRandom.GenerateAPIKey();
// Generate an array of 10 random bytes
byte[] b = RdRandom.GenerateBytes(10);
// Generate a random unsigned int
uint i = RdRandom.GenerateUnsignedInt();
Jika Anda tidak memiliki CPU yang kompatibel untuk menjalankan kode, gunakan saja layanan RESTful di rdrand.com. Dengan perpustakaan pembungkus RdRandom termasuk dalam proyek Anda, Anda hanya perlu melakukan ini (Anda mendapatkan 1000 panggilan gratis saat mendaftar):
string ret = Randomizer.GenerateKey(<length>, "<key>");
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
Meskipun tidak apa-apa:
Random random = new Random();
int randomNumber = random.Next()
Anda ingin mengontrol batas (min dan max mumbers) sebagian besar waktu. Jadi, Anda perlu menentukan di mana angka acak dimulai dan berakhir.
The Next()
Metode menerima dua parameter, min dan max.
Jadi jika saya ingin nomor acak saya antara katakan 5 dan 15, saya akan melakukannya
int randomNumber = random.Next(5, 16)
Ini kelas yang saya gunakan. Bekerja sepertiRandomNumber.GenerateRandom(1, 666)
internal static class RandomNumber
{
private static Random r = new Random();
private static object l = new object();
private static Random globalRandom = new Random();
[ThreadStatic]
private static Random localRandom;
public static int GenerateNewRandom(int min, int max)
{
return new Random().Next(min, max);
}
public static int GenerateLockedRandom(int min, int max)
{
int result;
lock (RandomNumber.l)
{
result = RandomNumber.r.Next(min, max);
}
return result;
}
public static int GenerateRandom(int min, int max)
{
Random random = RandomNumber.localRandom;
if (random == null)
{
int seed;
lock (RandomNumber.globalRandom)
{
seed = RandomNumber.globalRandom.Next();
}
random = (RandomNumber.localRandom = new Random(seed));
}
return random.Next(min, max);
}
}
Saya ingin menunjukkan apa yang terjadi ketika generator acak baru digunakan setiap saat. Misalkan Anda memiliki dua metode atau dua kelas yang masing-masing membutuhkan nomor acak. Dan secara naif Anda mengkodekannya seperti:
public class A
{
public A()
{
var rnd=new Random();
ID=rnd.Next();
}
public int ID { get; private set; }
}
public class B
{
public B()
{
var rnd=new Random();
ID=rnd.Next();
}
public int ID { get; private set; }
}
Apakah Anda pikir Anda akan mendapatkan dua ID yang berbeda? NGGAK
class Program
{
static void Main(string[] args)
{
A a=new A();
B b=new B();
int ida=a.ID, idb=b.ID;
// ida = 1452879101
// idb = 1452879101
}
}
Solusinya adalah selalu menggunakan generator acak statis tunggal. Seperti ini:
public static class Utils
{
public static readonly Random random=new Random();
}
public class A
{
public A()
{
ID=Utils.random.Next();
}
public int ID { get; private set; }
}
public class B
{
public B()
{
ID=Utils.random.Next();
}
public int ID { get; private set; }
}
RNGCryptoServiceProvider
adalah panggilan yang lebih baik.
Untuk seed acak yang kuat, saya selalu menggunakan CryptoRNG dan bukan Time.
using System;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
var random = new Random(GetSeed());
Console.WriteLine(random.Next());
}
public static int GetSeed()
{
using (var rng = new RNGCryptoServiceProvider())
{
var intBytes = new byte[4];
rng.GetBytes(intBytes);
return BitConverter.ToInt32(intBytes, 0);
}
}
}
Random random = new Random ();
int randomNumber = random.Next (lowerBound,upperBound);
Sama seperti catatan untuk referensi di masa mendatang.
Jika Anda menggunakan .NET Core, beberapa instance Acak tidak berbahaya seperti sebelumnya. Saya menyadari bahwa pertanyaan ini berasal dari 2010, tetapi karena pertanyaan ini sudah lama tetapi memiliki beberapa daya tarik, saya pikir itu hal yang baik untuk mendokumentasikan perubahan.
Anda dapat merujuk ke pertanyaan yang saya buat beberapa waktu lalu:
Apakah Microsoft mengubah seed default Acak?
Pada dasarnya, mereka telah mengubah seed default dari Environment.TickCount
menjadi Guid.NewGuid().GetHashCode()
, jadi jika Anda membuat 2 instance Random, ia tidak akan menampilkan angka yang sama.
Anda dapat melihat perbedaan file dari .NET Framework / .NET Core (2.0.0+) di sini: https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d
Ini tidak seaman RNGCryptoServiceProvider, tapi setidaknya itu tidak akan memberi Anda hasil yang aneh.
Interop.GetRandomBytes((byte*)&result, sizeof(int));
.
Angka yang dihitung oleh komputer melalui proses deterministik, tidak dapat, menurut definisi, menjadi acak.
Jika Anda menginginkan angka acak asli, keacakan berasal dari kebisingan atmosfer atau peluruhan radioaktif.
Anda dapat mencoba misalnya RANDOM.ORG (ini mengurangi kinerja)
Random rand = new Random();
int name = rand.Next()
Masukkan nilai apa pun yang Anda inginkan dalam tanda kurung kedua pastikan Anda telah menetapkan nama dengan menulis prop dan double tab untuk menghasilkan kode
Jika Anda ingin CSRNG menghasilkan angka acak antara min dan maks, ini untuk Anda. Ini akan menginisialisasi Random
kelas dengan benih acak aman.
class SecureRandom : Random
{
public static byte[] GetBytes(ulong length)
{
RNGCryptoServiceProvider RNG = new RNGCryptoServiceProvider();
byte[] bytes = new byte[length];
RNG.GetBytes(bytes);
RNG.Dispose();
return bytes;
}
public SecureRandom() : base(BitConverter.ToInt32(GetBytes(4), 0))
{
}
public int GetRandomInt(int min, int max)
{
int treashold = max - min;
if(treashold != Math.Abs(treashold))
{
throw new ArithmeticException("The minimum value can't exceed the maximum value!");
}
if (treashold == 0)
{
throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
}
return min + (Next() % treashold);
}
public static int GetRandomIntStatic(int min, int max)
{
int treashold = max - min;
if (treashold != Math.Abs(treashold))
{
throw new ArithmeticException("The minimum value can't exceed the maximum value!");
}
if(treashold == 0)
{
throw new ArithmeticException("The minimum value can't be the same as the maximum value!");
}
return min + (BitConverter.ToInt32(GetBytes(4), 0) % treashold);
}
}
Maaf, OP memang membutuhkan int
nilai acak , tetapi untuk tujuan sederhana berbagi pengetahuan jika Anda menginginkan BigInteger
nilai acak, Anda dapat menggunakan pernyataan berikut:
BigInteger randomVal = BigInteger.Abs(BigInteger.Parse(Guid.NewGuid().ToString().Replace("-",""), NumberStyles.AllowHexSpecifier));
Saya akan berasumsi bahwa Anda ingin generator nomor acak terdistribusi secara merata seperti di bawah ini. Nomor acak di sebagian besar bahasa pemrograman termasuk C # dan C ++ tidak dikocok dengan benar sebelum menggunakannya. Ini berarti Anda akan mendapatkan nomor yang sama berulang-ulang, yang sebenarnya tidak acak. Untuk menghindari menggambar nomor yang sama berulang-ulang, Anda perlu seed. Biasanya, ticks in time tidak masalah untuk tugas ini. Ingatlah bahwa Anda akan mendapatkan nomor yang sama berulang kali jika Anda menggunakan benih yang sama setiap waktu. Jadi cobalah selalu menggunakan benih yang bervariasi. Waktu adalah sumber yang baik untuk benih karena mereka selalu mengejar.
int GetRandomNumber(int min, int max)
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(min, max);
}
jika Anda mencari generator angka acak untuk distribusi normal, Anda mungkin menggunakan transformasi Box-Muller. Periksa jawabannya oleh yoyoyoyosef di Random Gaussian Variable Question. Karena Anda ingin integer, Anda harus memberikan nilai ganda ke integer pada akhirnya.
Random rand = new Random(); //reuse this if you are generating many
double u1 = 1.0-rand.NextDouble(); //uniform(0,1] random doubles
double u2 = 1.0-rand.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
double randNormal =
mean + stdDev * randStdNormal; //random normal(mean,stdDev^2)
Cara termudah mungkin hanya Random.range(1, 3)
Ini akan menghasilkan angka antara 1 dan 2.
Anda dapat mencoba dengan nilai seed acak menggunakan di bawah ini:
var rnd = new Random(11111111); //note: seed value is 11111111
string randomDigits = rnd.Next();
var requestNumber = $"SD-{randomDigits}";
Kenapa tidak digunakan int randomNumber = Random.Range(start_range, end_range)
?
Gunakan satu contoh Acak berulang kali
// Somewhat better code...
Random rng = new Random();
for (int i = 0; i < 100; i++)
{
Console.WriteLine(GenerateDigit(rng));
}
...
static int GenerateDigit(Random rng)
{
// Assume there'd be more logic here really
return rng.Next(10);
}
Artikel ini membahas mengapa keacakan menyebabkan begitu banyak masalah, dan bagaimana cara mengatasinya. http://csharpindepth.com/Articles/Chapter12/Random.aspx
Random
bukan kelas thread aman. Jika Anda membuat satu instance, Anda harus membatasi aksesnya di belakang mekanisme penguncian.
Coba langkah-langkah sederhana ini untuk membuat angka acak:
Buat fungsi:
private int randomnumber(int min, int max)
{
Random rnum = new Random();
return rnum.Next(min, max);
}
Gunakan fungsi di atas di lokasi di mana Anda ingin menggunakan angka acak. Misalkan Anda ingin menggunakannya dalam kotak teks.
textBox1.Text = randomnumber(0, 999).ToString();
0 minimum dan 999 maks. Anda dapat mengubah nilai menjadi apa pun yang Anda inginkan.
Saya selalu memiliki metode yang menghasilkan angka acak yang membantu untuk berbagai keperluan. Saya harap ini dapat membantu Anda juga:
public class RandomGenerator
{
public int RandomNumber(int min, int max)
{
var random = new Random();
return random.Next(min, max);
}
public string RandomString(int size, bool lowerCase)
{
var builder = new StringBuilder();
var random = new Random();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
if (lowerCase)
return builder.ToString().ToLower();
return builder.ToString();
}
}
Cepat dan mudah untuk inline, gunakan kode di bawah ini:
new Random().Next(min, max);
// for example unique name
strName += "_" + new Random().Next(100, 999);