Öncelikle, bağladığınız sunum, güvenlik amacıyla yalnızca rastgele sayılardan bahsediyor. Dolayısıyla Random
, güvenlik dışı amaçlar için kötü olduğunu iddia etmiyor .
Ama öyle olduğunu iddia ediyorum. .Net 4 uygulaması Random
birkaç yönden kusurludur. Rastgele sayılarınızın kalitesini umursamıyorsanız, yalnızca kullanmanızı öneririm. Daha iyi üçüncü taraf uygulamaları kullanmanızı tavsiye ederim.
Hata 1: Tohumlama
Varsayılan yapıcı geçerli saat ile tohumlar. Bu nedenle Random
, kısa bir zaman çerçevesi içinde (yaklaşık 10 ms) varsayılan kurucu ile oluşturulan tüm örnekler aynı sırayı döndürür. Bu belgelenmiştir ve "tasarım gereği". Kodunuzu çoklu iş parçacığı yapmak istiyorsanız, bu özellikle can sıkıcıdır, çünkü Random
her iş parçacığının çalıştırılmasının başında bir örnek oluşturamazsınız .
Çözüm, varsayılan oluşturucuyu kullanırken çok dikkatli olmak ve gerektiğinde el ile tohumlamaktır.
Buradaki bir başka sorun da çekirdek boşluğunun oldukça küçük olmasıdır (31 bit). Dolayısıyla Random
, tamamen rastgele tohumlarla 50 bin örnek oluşturursanız , muhtemelen iki kez rastgele bir sayı dizisi elde edersiniz ( doğum günü paradoksu nedeniyle ). Yani manuel tohumlamanın doğru yapılması da kolay değil.
Hata 2: Döndürülen rastgele sayıların dağılımı Next(int maxValue)
önyargılıdır
Next(int maxValue)
Açıkça tek tip olmayan parametreler var . Örneğin, hesaplarsanız , örneklerin yaklaşık 2 / 3'ünü r.Next(1431655765) % 2
alırsınız 0
. (Cevabın sonundaki örnek kod.)
Hata 3: NextBytes()
Yöntem verimsizdir.
Bayt başına maliyet, NextBytes()
tam bir tamsayı örneği oluşturmanın maliyeti kadar büyüktür Next()
. Bundan gerçekten bayt başına bir örnek oluşturduklarından şüpheleniyorum.
Her örnekten 3 bayt kullanan daha iyi bir uygulama NextBytes()
, neredeyse 3 faktör kadar hızlanacaktır .
Bu kusur sayesinde makinemden (Win7, Core i3 2600MHz) Random.NextBytes()
sadece yaklaşık% 25 daha hızlı System.Security.Cryptography.RNGCryptoServiceProvider.GetBytes
.
Eminim biri kaynak / derlenmiş bayt kodunu incelese, kara kutu analizimde bulduğumdan daha fazla kusur bulacaktır.
Kod örnekleri
r.Next(0x55555555) % 2
çok önyargılı:
Random r = new Random();
const int mod = 2;
int[] hist = new int[mod];
for(int i = 0; i < 10000000; i++)
{
int num = r.Next(0x55555555);
int num2 = num % 2;
hist[num2]++;
}
for(int i=0;i<mod;i++)
Console.WriteLine(hist[i]);
Verim:
byte[] bytes=new byte[8*1024];
var cr=new System.Security.Cryptography.RNGCryptoServiceProvider();
Random r=new Random();
for(int i=0;i<100000;i++)
{
r.NextBytes(bytes);
}
for(int i=0;i<100000;i++)
{
for(int j=0;j<bytes.Length;j++)
bytes[j]=(byte)r.Next();
}
for(int i=0;i<100000;i++)
{
for(int j=0;j+2<bytes.Length;j+=3)
{
int num=r.Next();
bytes[j+2]=(byte)(num>>16);
bytes[j+1]=(byte)(num>>8);
bytes[j]=(byte)num;
}
}
for(int i=0;i<100000;i++)
{
cr.GetBytes(bytes);
}