Giriş
C ile srand() ve rand() metodları kullanılarak rastgele sayılar üretilebilir. Üretici ilklendirmek için srand() metodu yazısına bakabilirsiniz.
rand artık kullanılmamalı
Açıklaması şöyle.
rand() metodu global state kullanır. Bu yüzden önceden belirlenmiş bir diziye ihtiyacımız varsa kesinlikle kullanılmamalıdır.
rand Gerçekleştirimi Nasıldır?
rand() Gerçekleştirimi İçin Algoritmalar yazısına taşıdım.
Örnek
Şöyle yaparız
rand()'ın ne kadar çift sayı ürettiğini görmek için şöyle yaparız
C ile srand() ve rand() metodları kullanılarak rastgele sayılar üretilebilir. Üretici ilklendirmek için srand() metodu yazısına bakabilirsiniz.
rand artık kullanılmamalı
Açıklaması şöyle.
rand ve global stateUse of rand therefore continues to be non-portable, with unpredictable and oft-questionable quality and performance.
rand() metodu global state kullanır. Bu yüzden önceden belirlenmiş bir diziye ihtiyacımız varsa kesinlikle kullanılmamalıdır.
rand Gerçekleştirimi Nasıldır?
rand() Gerçekleştirimi İçin Algoritmalar yazısına taşıdım.
Aynı Sayı Tekrar Üretilebilir mi ?
Sorunun cevabı evet.Örnek
Şöyle yaparız
assert(rand() != rand());
Bu kodda koşulunun sağlanmadığı görülebilir.#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
unsigned int i;
for(i = 0; ; i++) {
int r = rand();
if (r == rand()) {
printf("Oops. rand() = %d; i = %d\n", r, i);
break;
}
}
return 0;
}
Örnekrand()'ın ne kadar çift sayı ürettiğini görmek için şöyle yaparız
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main() {
size_t size = ((size_t)RAND_MAX) + 1;
char *randoms = calloc(size, sizeof(char));
int dups = 0;
srand(time(0));
for (int i = 0; i < RAND_MAX; i++) {
int r = rand();
if (randoms[r]) {
// printf("duplicate at %d\n", r);
dups++;
}
randoms[r] = 1;
}
printf("duplicates: %d\n", dups);
}
rand() ne Döndürür
rand() metodu genellikle 15 bitlik sayılar üretir. 15 bit olması garanti değildir. Bu yüzden RAND_MAX macrosunu kullanmak gerekir. Yani rand() 0 - RAND_MAX arasında bir sayı üretir, negatif sayı üretmez.
RAND_MAX'ın en az 32767 değerine eşit olması garanti edilmiştir. Windows üzerinde RAND_MAX 32767 (5 haneli rakam) değerine eşittir. Linux üzerinde ise 2147483647 (10 haneli rakam) değerine eşittir.
How to store a random number into a null-terminated character array? sorusunda uzunluk farkına dikkat çekiliyor.
rand() Thread Safe Midir ?
Posix sistemlerde rand() meteodu thread-safe değildir.
Üretilen Sayı Dağılımı Nasıldır?
Bir diğer önemli nokta ise rand() Uniform Distribution (tek düze dağılım) sayı üretir. Bir üretecin Uniform Distribution olduğunun nasıl ispatlandığını anlamak için buraya göz atabilirsiniz
.
Dağılım Sınıfları Var Mıdır?
Dağılımı ayarlamak için bir çok kütüphane dağılım sınıfları sunmakta. Maalesef C kütüphanesinde dağılım sınıfı yok.
Dağılımda Bias'a Dikkat
Şu kod tavsiye edilmiyor. Bu tarz kodlar yerine std::uniform_int_distribution sınıfını kullamak daha iyi.
Şöyle yaparız.
Ağırlığa Göre Dağılım
Örnek
Şöyle yaparız. %33 oranında BLUE, %66 oranında ise WHITE çıkan bir dağılım var. rand() %3 [0,2] arasında bir değer döner. 0 gelirse (%33) BLUE, 1 ve iki gelirse (%66) oranında WHITE döner.
Benzer bir şeyi Java'da şöyle yaparız. 0 - 1000 arasında sayı ütetilir. Bu sayı 10 ile bölünerek 0 - 100 arasına getirilir. %60'ı 0 olur, %40'ı ise 10 ile gölünmüş hali olur.
Kriptografik üreteçlerde olduğu gibi random byte üretmek için şöyle yaparız.
RAND_MAX'ın en az 32767 değerine eşit olması garanti edilmiştir. Windows üzerinde RAND_MAX 32767 (5 haneli rakam) değerine eşittir. Linux üzerinde ise 2147483647 (10 haneli rakam) değerine eşittir.
How to store a random number into a null-terminated character array? sorusunda uzunluk farkına dikkat çekiliyor.
rand() Thread Safe Midir ?
Posix sistemlerde rand() meteodu thread-safe değildir.
Bu yüzden aşağıda anlatılan rand_r() metodunu (bilinçsiz kullanılırsa yine thread-safe olmaz!) kullanmak gerekir.Windows'ta ise rand_s()'i kullanmak gerekir.The function rand() is not reentrant or thread-safe, since it uses hidden state that is modified on each call.
Üretilen Sayı Dağılımı Nasıldır?
Bir diğer önemli nokta ise rand() Uniform Distribution (tek düze dağılım) sayı üretir. Bir üretecin Uniform Distribution olduğunun nasıl ispatlandığını anlamak için buraya göz atabilirsiniz
.
Dağılım Sınıfları Var Mıdır?
Dağılımı ayarlamak için bir çok kütüphane dağılım sınıfları sunmakta. Maalesef C kütüphanesinde dağılım sınıfı yok.
Dağılımda Bias'a Dikkat
Şu kod tavsiye edilmiyor. Bu tarz kodlar yerine std::uniform_int_distribution sınıfını kullamak daha iyi.
int x = 7;
while(x > 6)
x = 1 + std::rand()/((RAND_MAX + 1u)/6); // Note: 1+rand()%6 is biased
Uniform Real DistributionŞöyle yaparız.
double probability = (rand()/(double)(RAND_MAX + 1));
Ağırlığa Göre Dağılım
Örnek
Şöyle yaparız. %33 oranında BLUE, %66 oranında ise WHITE çıkan bir dağılım var. rand() %3 [0,2] arasında bir değer döner. 0 gelirse (%33) BLUE, 1 ve iki gelirse (%66) oranında WHITE döner.
#define BLUE 1
#define WHITE 2
int whichBall()
{
int val = rand() % 3;
if (val == 0)
return BLUE;
return WHITE;
}
ÖrnekBenzer bir şeyi Java'da şöyle yaparız. 0 - 1000 arasında sayı ütetilir. Bu sayı 10 ile bölünerek 0 - 100 arasına getirilir. %60'ı 0 olur, %40'ı ise 10 ile gölünmüş hali olur.
Stream<Integer> boxed = random.ints(0, 1000).map(r -> r%10 < 6 ? 0 : r/10).boxed();
Random Byte ÜretmekKriptografik üreteçlerde olduğu gibi random byte üretmek için şöyle yaparız.
#include <stdlib.h>
#include <limits.h>
#include <math.h>
/* Assumes srand() has been called with an appropriate seed at some point
Code assumes C99 is available; minor tweaks needed for older compilers.
*/
int gen_random_int() {
const int BITS_PER_RAND = (int)log2(RAND_MAX + 1);
int ret = 0;
for (int i = 0; i < sizeof(int) * CHAR_BIT; i += BITS_PER_RAND) {
ret <<= BITS_PER_RAND;
ret |= rand();
}
return ret;
}
Hiç yorum yok:
Yorum Gönder