Saya memiliki fungsi berikut:
//Function to get random number
public static int RandomNumber(int min, int max)
{
Random random = new Random();
return random.Next(min, max);
}
Bagaimana saya menyebutnya:
byte[] mac = new byte[6];
for (int x = 0; x < 6; ++x)
mac[x] = (byte)(Misc.RandomNumber((int)0xFFFF, (int)0xFFFFFF) % 256);
Jika saya langkah loop itu dengan debugger selama runtime saya mendapatkan nilai yang berbeda (yang saya inginkan). Namun, jika saya meletakkan breakpoint dua baris di bawah kode itu, semua anggota mac
array memiliki nilai yang sama.
Mengapa itu terjadi?
new Random().Next((int)0xFFFF, (int)0xFFFFFF) % 256);
tidak menghasilkan angka "acak" yang lebih baik dari.Next(0, 256)
Rand.Next(int, int)
metode statis yang menyediakan akses statis ke nilai acak tanpa mengunci atau mengalami masalah penggunaan kembali unggulanJawaban:
Setiap kali Anda melakukannya
new Random()
diinisialisasi menggunakan jam. 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 .Sunting (lihat komentar): mengapa kita perlu di
lock
sini?Pada dasarnya,
Next
akan mengubah keadaan internalRandom
instance. Jika kami melakukan itu secara bersamaan dari beberapa utas, Anda dapat berdebat "kami baru saja membuat hasilnya lebih acak", tetapi apa yang sebenarnya kami lakukan berpotensi melanggar implementasi internal, dan kami juga bisa mulai mendapatkan angka yang sama dari utas berbeda, yang mungkin menjadi masalah - dan mungkin tidak. Namun, jaminan apa yang terjadi secara internal adalah masalah yang lebih besar; karenaRandom
tidak tidak membuat jaminan benang-keselamatan. Jadi ada dua pendekatan yang valid:Random
contoh berbeda per utasBaik bisa baik-baik saja; tetapi mutexing satu contoh dari beberapa penelepon pada saat yang sama hanya meminta masalah.
The
lock
mencapai pertama (dan sederhana) dari pendekatan ini; Namun, pendekatan lain mungkin:ini kemudian per-utas, jadi Anda tidak perlu melakukan sinkronisasi.
sumber
lock (syncObject)
hanya akan membantu jika semuarandom.Next()
panggilan juga ada di dalamlock (syncObject)
. Jika skenario yang Anda gambarkan benar-benar terjadi bahkan denganlock
penggunaan yang benar , itu juga sangat mungkin terjadi dalam skenario single-threaded (mis.Random
Rusak secara halus).Untuk kemudahan penggunaan ulang di seluruh aplikasi Anda, sebuah kelas statis dapat membantu.
Anda dapat menggunakan lalu menggunakan contoh acak statis dengan kode seperti
sumber
Solusi Mark bisa sangat mahal karena perlu melakukan sinkronisasi setiap kali.
Kita dapat menyiasati kebutuhan untuk sinkronisasi dengan menggunakan pola penyimpanan khusus thread:
Ukur kedua implementasi dan Anda akan melihat perbedaan yang signifikan.
sumber
Random
contoh global tambahan untuk mendapatkan benih adalah ide bagus. Perhatikan juga bahwa kode dapat lebih disederhanakan menggunakanThreadLocal<T>
kelas yang diperkenalkan di .NET 4 (seperti yang ditulis Phil di bawah ).Jawaban saya dari sini :
Hanya mengulangi solusi yang tepat :
Jadi, Anda dapat menelepon:
semua di seluruh.
Jika Anda benar-benar membutuhkan metode statis stateless sejati untuk menghasilkan angka acak, Anda bisa mengandalkan a
Guid
.Ini akan menjadi sedikit lebih lambat, tetapi bisa jauh lebih acak daripada
Random.Next
, setidaknya dari pengalaman saya.Tapi tidak :
Pembuatan objek yang tidak perlu akan membuatnya lebih lambat terutama di bawah satu lingkaran.
Dan tidak pernah :
Tidak hanya lebih lambat (di dalam satu lingkaran), keacakannya adalah ... yah tidak benar-benar bagus menurut saya ..
sumber
Random
kelas cocok dengan kasus 2 (dengan demikian, kasus 1 juga). Anda hanya dapat mengganti penggunaanRandom
oleh AndaGuid+Hash
jika Anda tidak dalam kasus 2. Kasus 1 mungkin cukup untuk menjawab Pertanyaan, dan kemudian,Guid+Hash
pekerjaan Anda baik-baik saja. Tetapi tidak jelas dikatakan (ps: seragam ini )Random
danGuid.NewGuid().GetHashCode()
melalui Ent ( fourmilab.ch/random ) dan keduanya sama-sama acak.new Random(Guid.NewGuid().GetHashCode())
berfungsi dengan baik, seperti halnya menggunakan "master" yang disinkronkanRandom
untuk menghasilkan benih untuk "anak"Random
. Tentu saja, itu tergantung pada bagaimana sistem Anda menghasilkan Panduan - untuk sistem saya, mereka cukup acak, dan pada orang lain mungkin bahkan menjadi crypto-random. Jadi Windows atau MS SQL tampaknya baik-baik saja saat ini. Mono dan / atau ponsel mungkin berbeda.GetHashCode
Guid dalam. NET berasal dari representasi string-nya. Outputnya cukup acak sesuai dengan keinginan saya.Saya lebih suka menggunakan kelas berikut untuk menghasilkan angka acak:
sumber
1) Seperti yang dikatakan Marc Gravell, coba gunakan ONE-generator acak. Itu selalu keren untuk menambahkan ini ke konstruktor: System.Environment.TickCount.
2) Satu tip. Katakanlah Anda ingin membuat 100 objek dan anggap masing-masing dari mereka harus memiliki generator acak sendiri (berguna jika Anda menghitung LOADS angka acak dalam waktu yang sangat singkat). Jika Anda melakukan ini dalam satu lingkaran (generasi 100 objek), Anda bisa melakukan ini seperti itu (untuk memastikan keacakan sepenuhnya):
Bersulang.
sumber
Random()
constructor panggilanRandom(Environment.TickCount)
pulaSetiap kali Anda mengeksekusi
Tidak masalah jika Anda mengeksekusinya jutaan kali, Anda akan selalu menggunakan seed yang sama.
Jika Anda menggunakan
Anda mendapatkan urutan nomor acak yang berbeda, jika seorang hacker menebak benih dan algoritma Anda terkait dengan keamanan sistem Anda - algoritma Anda rusak. Saya Anda menjalankan mult. Dalam konstruktor ini, seed ditentukan oleh jam sistem dan jika beberapa instance dibuat dalam periode waktu yang sangat singkat (milidetik), mungkin saja mereka memiliki seed yang sama.
Jika Anda membutuhkan nomor acak yang aman, Anda harus menggunakan kelas
Pemakaian:
sumber
It does not matter if you execute it millions of times, you will always use the same seed.
Itu tidak benar kecuali jika Anda menentukan sendiri benihnya.cukup deklarasikan variabel kelas acak seperti ini:
jika Anda ingin mendapatkan nomor acak yang berbeda setiap kali dari daftar Anda maka gunakan
Setiap kali dengan mendeklarasikan
Random r = new Random()
sekali.sumber
new Random()
menggunakan jam sistem, tetapi jika Anda memanggil seluruh kode itu dua kali berturut-turut sebelum jam berubah, Anda akan mendapatkan nomor acak yang sama. Itulah inti dari jawaban di atas.Ada banyak solusi, di sini satu: jika Anda hanya ingin menghapus nomor surat dan metode menerima secara acak dan panjang hasilnya.
sumber
Random
contoh, tetapi Anda masih mengharapkan penelepon untuk membuat contoh bersama. Jika pemanggil membuat instance baru setiap kali dan kode dieksekusi dua kali sebelum jam berubah, Anda akan mendapatkan nomor acak yang sama. Jadi jawaban ini masih membuat asumsi yang bisa salah.