Bagaimana saya menghasilkan bilangan bulat acak di C#?
The Random
kelas adalah digunakan untuk membuat angka acak. (Pseudo-random yang tentu saja.).
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 akan membuat lebih dari satu nomor acak, anda harus menjaga Random
contoh dan menggunakannya kembali. Jika anda membuat kasus baru juga dalam waktu dekat, mereka akan memproduksi seri yang sama dari angka acak sebagai random generator adalah unggulan dari jam sistem.
Pertanyaan terlihat sangat sederhana tapi jawabannya agak rumit. Jika anda melihat hampir semua orang telah menyarankan untuk menggunakan Random kelas dan beberapa telah menyarankan untuk menggunakan RNG crypto kelas. Tapi kemudian ketika memilih apa.
Untuk itu kita perlu memahami terlebih dahulu istilah KEACAKAN dan filosofi di balik itu.
Saya akan mendorong anda untuk menonton video ini yang terjadi di kedalaman dalam filsafat ACAK menggunakan C# [
Hal pertama mari kita memahami filosofi dari KEACAKAN. Ketika kita mengatakan seseorang untuk memilih antara MERAH, HIJAU dan KUNING yang terjadi secara internal. Apa yang membuat seseorang memilih MERAH atau KUNING atau HIJAU?
Beberapa pemikiran awal masuk ke pikiran orang yang memutuskan pilihannya, hal ini dapat menjadi warna favorit , warna keberuntungan, dan sebagainya. Dengan kata lain beberapa pemicu awal yang kita istilah di ACAK sebagai BENIH.BENIH ini adalah titik awal, pemicu yang mendorong dia untuk memilih nilai ACAK.
Sekarang jika BENIH lebih mudah untuk menebak maka orang-orang semacam angka acak yang disebut sebagai PSEUDO dan ketika benih adalah sulit untuk menebak angka-angka acak yang disebut DIJAMIN angka acak.
Misalnya seseorang memilih warna tergantung pada cuaca dan kombinasi suara maka akan sulit untuk menebak awal benih.
Sekarang mari saya membuat sebuah pernyataan penting:-
*"Random" kelas hanya menghasilkan PSEUDO random number dan untuk menghasilkan SECURE random number kita perlu menggunakan "RNGCryptoServiceProvider" kelas.
Random kelas mengambil benih nilai-nilai dari CPU clock yang sangat banyak dapat diprediksi. Jadi dengan kata lain secara ACAK kelas dari C# menghasilkan nomor acak semu , di bawah ini adalah kode yang sama.
Catatan: .NET Core 2.0.0+
menggunakan benih yang berbeda pada parameterless konstruktor: bukan CPU clock ini menggunakan Guid.NewGuid().GetHashCode()
.
var random = new Random();
int randomnumber = random.Next()
Sedangkan RNGCryptoServiceProvider
kelas menggunakan OS entropi untuk menghasilkan biji. OS entropi adalah sebuah nilai acak yang dihasilkan dengan menggunakan suara, klik mouse, dan keyboard timing, termal, suhu dll. Di bawah ini berjalan dengan kode yang sama.
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[5];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
}
Untuk memahami OS entropi melihat video ini dari 14:30 [
di mana logika OS entropi adalah menjelaskan. Jadi menempatkan dalam kata-kata sederhana RNG Crypto menghasilkan MENGAMANKAN angka acak.Setiap kali anda melakukan new Random() diinisialisasi . Ini berarti bahwa dalam sebuah lingkaran yang ketat, anda mendapatkan nilai yang sama banyak kali. Anda harus tetap tunggal Acak contoh dan tetap menggunakan Berikutnya pada contoh 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);
}
}
Berhati-hatilah bahwa new Random()
lebih diunggulkan pada saat ini timestamp.
Jika anda ingin menghasilkan hanya satu nomor anda dapat menggunakan:
new Random().Berikutnya( int.MinValue, int.MaxValue )
Untuk informasi lebih lanjut, lihat di Random class, meskipun perhatikan:
Namun, karena jam ini memiliki resolusi terbatas, menggunakan parameterless konstruktor untuk membuat berbagai benda-benda Acak di dekat turut menciptakan generator nomor acak yang menghasilkan identik urutan angka acak
Jadi tidak menggunakan kode ini untuk menghasilkan serangkaian nomor acak.
Saya ingin menambahkan cryptographically secure versi:
RNGCryptoServiceProvider Kelas ([MEDIA][1] atau dotnetperls)
Menerapkan IDisposable.
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] randomNumber = new byte[4];//4 for int32
rng.GetBytes(randomNumber);
int value = BitConverter.ToInt32(randomNumber, 0);
}
[1]: https://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider(v=vs. 110).aspx
Anda bisa menggunakan Jon Skeet's StaticRandom metode dalam MiscUtil kelas perpustakaan yang dibangun untuk pseudo-random number.
using MiscUtil;
...
for (int i = 0; i < 100;
Console.WriteLine(StaticRandom.Next());
it's baik untuk benih Acak objek dengan saat ini milidetik, untuk memastikan benar-benar acak nomor, dan anda hampir tidak't menemukan duplikat menggunakannya berkali-kali
Random rand = new Random(DateTime.Now.Millisecond);
Update
Saya tahu bahwa new Random()
menggunakan arus kutu sebagai benih, tetapi penyemaian dengan saat ini milidetik masih cukup baik sebagai it's good start acak
Yang terakhir titik bahwa anda don't harus menginisialisasi new Random()
setiap kali anda memerlukan nomor acak, memulai salah satu objek Acak kemudian menggunakannya sebanyak yang anda butuhkan di dalam sebuah loop atau apapun
I've mencoba semua solusi ini tidak termasuk COBOL menjawab... lol
Tidak ada solusi yang cukup baik. Aku butuh randoms secara cepat untuk int loop dan saya mendapatkan ton dari nilai-nilai duplikat bahkan sangat beragam. Setelah menetap untuk jenis hasil acak terlalu lama akhirnya saya memutuskan untuk mengatasi masalah ini sekali dan untuk semua.
It's semua tentang benih.
Saya membuat random integer dengan parsing non-digit dari Guid, maka saya menggunakan itu untuk instantiate saya Acak kelas.
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);
}
Update: Pembenihan isn't diperlukan jika anda instantiate Acak kelas sekali. Jadi itu'd menjadi yang terbaik untuk membuat statis kelas dan memanggil metode dari 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);
}
}
Kemudian anda dapat menggunakan statis kelas seperti begitu..
for(var i = 0; i < 1000; i++)
{
int randomNumber = IntUtil.Random(1,100);
Console.WriteLine(randomNumber);
}
Saya akui saya suka pendekatan ini lebih baik.
Modifikasi jawaban dari di sini.
Jika anda memiliki akses ke Intel Secure Key CPU yang kompatibel, anda dapat menghasilkan angka acak nyata dan string menggunakan perpustakaan ini: https://github.com/JebteK/RdRand dan https://www.rdrand.com/
Hanya men-download versi terbaru dari di sini, termasuk Jebtek.RdRand dan tambahkan dengan menggunakan pernyataan untuk itu. Kemudian, semua 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 don't memiliki CPU yang kompatibel untuk mengeksekusi kode, hanya menggunakan layanan Tenang di rdrand.com. Dengan RdRandom wrapper perpustakaan termasuk dalam proyek anda, anda hanya akan perlu untuk melakukan hal ini (anda mendapatkan 1000 panggilan gratis ketika anda mendaftar):
string ret = Randomizer.GenerateKey(<length>, "<key>");
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
Angka-angka yang dihasilkan oleh built-in Random
kelas (Sistem.Random) menghasilkan nomor acak semu.
Jika anda ingin benar acak angka, yang terdekat yang bisa kita dapatkan adalah "secure Pseudo Random Generator" yang dapat dihasilkan dengan menggunakan Kriptografi kelas dalam C# seperti RNGCryptoServiceProvider
.
Meski begitu, jika anda masih perlu benar angka acak yang anda akan perlu untuk menggunakan sumber eksternal seperti perangkat akuntansi untuk peluruhan radioaktif sebagai benih untuk nomor acak generator. Karena, menurut definisi, setiap nomor yang dihasilkan oleh murni algoritmik berarti tidak dapat benar-benar acak.
Ini adalah kelas yang saya gunakan. Bekerja seperti RandomNumber.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);
}
}
Saat ini baik-baik saja:
Random random = new Random();
int randomNumber = random.Next()
Anda'd ingin mengontrol batas (min dan max mumbers) sebagian besar waktu. Jadi, anda perlu menentukan di mana nomor acak dimulai dan berakhir.
Next()
metode menerima dua parameter, min dan max.
Jadi jika saya ingin nomor acak antara 5 dan 15 tahun, aku'd lakukan
int randomNumber = random.Next(5, 16)
Untuk kuat random seed aku selalu menggunakan CryptoRNG dan bukan Waktu.
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);
}
}
}
Angka-angka yang dihitung oleh komputer melalui deterministik proses, tidak bisa, oleh definisi, menjadi acak.
Jika anda ingin yang asli nomor acak, keacakan berasal dari atmosfer kebisingan atau peluruhan radioaktif.
Anda dapat mencoba untuk contoh RANDOM.ORG (mengurangi kinerja)
Saya ingin menunjukkan apa yang terjadi ketika baru acak generator digunakan setiap waktu. Misalkan anda memiliki dua metode atau dua kelas yang masing-masing memerlukan nomor acak. Dan naif anda kode mereka 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? TIDAK
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 untuk always menggunakan satu static random generator. 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; }
}
Berikut kode mengembalikan nomor acak.
int num = random.Next();
Berikut kode mengembalikan bilangan acak yang kurang dari 1000.
int num = random.Next(1000);
Berikut kode mengembalikan nomor acak antara min dan max range.
Menghasilkan yang random nomor antara dua nomor:
public int RandomNumber(int min, int max)
{
Random random = new Random();
return random.Next(min, max);
}