8 Temmuz 2020 Çarşamba

C programlana rastgele sayı üretme

RASTGELE SAYI ÜRETİMİ
Rasgele sayı üretimi matematiğin önemli konularından biridir. Rasgele sayılar ya da daha doğru
ifadeyle, rasgele izlenimi veren sayılar (sözde rasgele sayılar - pseudo random numbers)
istatistik, ekonomi, matematik gibi pekçok alanda olduğu gibi programcılıkta da
kullanılmaktadır.
Rasgele sayılar bir rasgele sayı üreticisi (random number generator) tarafından üretilirler.
Rasgele sayı üreticisi aslında matematiksel bir fonksiyondur. Söz konusu fonksiyon bir
başlangıç değeri alarak bir değer üretir. Daha sonra ürettiği her değeri girdi olarak alır ve
tekrar başka bir sayı üretir . Üreticinin ürettiği sayılar rasgele izlenimi vermektedir.
C standartları rasgele tamsayı üreten bir fonskiyonun standart bir C fonksiyonu olarak
tanımlanmasını zorunlu kılmıştır. Bu fonksiyonun prototip bildirimi aşağıdaki gibidir:
int rand(void);
C standartları rand fonksiyonunun rasgele sayı üretimi konusunda kullanacağı algoritma ya da
teknik üzerinde bir koşul koymamıştır. Bu konu derleyiciyi yazanların seçimine bağlı
(implementation dependent) bırakılmıştır. rand fonksiyonunun prototipi standart bir başlık
dosyası olan stdlib.h içinde bildirilmiştir.
Bu yüzden rand fonksiyonunun çağırılması durumunda bu başlık dosyası "include" önişlemci
komuduyla kaynak koda dahil edilmelidir.
#include <stdlib.h>
rand fonksiyonu her çağırıldığında [0, RAND_MAX] aralığında rasgele bir tamsayı değerini geri
döndürür. RAND_MAX stdlib.h başlık dosyası içinde tanımlanan bir sembolik sabittir,
derleyicilerin çoğunda RAND_MAX sembolik sabiti 32767 olarak, yani 2 byte'lık signed int
türünün maximum değeri olarak tenımlanmıştır.
Aşağıdaki program parçasında 0 ile 32767 arasında 10 adet rasgele sayı üretilerek ekrana
yazdırılmaktadır :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int k;
for (k = 0; k < 10; ++k)
printf("%d ", rand());
return 0;
}
Yukarıdaki kaynak kodla oluşturulan programın her çalıştırılmasında ekrana aynı sayılar
yazılacaktır. Örneğin yukarıdaki programı DOS altında Borland Turbo C 2.0 derleyicisi ile
derleyip çalıştırdığımızda ekran çıktısı aşağıdaki gibi oldu:
346 130 10982 1090 11656 7117 17595 6415 22948 31126
Oluşturulan program her çalıştırıldığında neden hep aynı sayı zinciri elde ediliyor? rand
fonksiyonu rasgele sayı üretmek için bir algoritma kullanıyor. Bu algoritma derleyiciden
derleyiciye değişsede, rasgele sayı üretiminde kullanılan ana tema aynıdır. Bir başlangıç değeri
ile işe başlanır. Buna tohum değer diyoruz. Bu değer üzerinde bazı işlemler yapılarak rasgele bir sayı elde edilir. Tohum değer üzerinde yapılan işlem bu kez elde edilen rasgele sayı
üzerinde tekrarlanır...
rand fonksiyonu rasgele sayı üretmek için bir başlangıç değeri kullanıyor. Rasgele sayı
üreticilerinin (random number generator) kullandıkları başlangıç değerine tohum değeri (seed)
denir. rand fonksiyonunu içeren programı her çalıştırdığımızda aynı tohum değerinden
başlayacağı için aynı sayı zinciri elde edilecektir. İşte ikinci fonksiyon olan srand fonksiyonu,
rasgele sayı üreticisinin tohum değerini değiştirmeye yarar:
void srand (unsigned seed);
srand fonksiyonuna gönderilen arguman rasgele sayı üreticisinin tohum değerini değiştir.
srand() fonksiyonuna başka bir tohum değeri gönderdiğimizde fonksiyonun ürettiği rasgele sayı
zinciri değişecektir. Yukarıdaki programa bir ilave yaparak yeniden çalıştırın.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int k;
srand(100);
for (k = 0; k < 10; ++k)
printf("%d ", rand());
return 0;
}
1862 11548 3973 4846 9095 16503 6335 13684 21357 21505
Ancak bu kez oluşturduğumuz programı her çelıştırdığımızda yine yukarıdaki sayı zinciri elde
edilecek. Zira rand fonksiyonunun kullanmakta olduğu önceden seçilmiş (default) tohum
değerini kullanmasak da, rasgele sayı üretme mekanizması bu kez her defasında bizim srand
fonksiyonuyla göndermiş olduğumuz tohum değerini kullanacak. Programı birkaç kere çalıştırıp
aynı sayı zincirini ürettiğini test edin.
Bir çok durumda programın her çalıştırılmasında aynı rasgele sayı zincirinin üretilmesi
istenmez. Programın her çalışmasında farklı bir sayı zincirinin elde edilmesi için programın her
çalışmasında srand fonksiyonu başka bir değerle, rasgele sayı üreticisinin tohum değerini set
etmelidir. Bu amaçla çoğu zaman time fonksiyonundan faydalanılır:
time fonksiyonu standart bir C fonksiyonudur, prototip bildirimi standart bir başlık dosyası olan
time.h içindedir. time fonksiyonu, parametre değişkeni gösterici olan bir fonksiyon olduğundan
ileride detaylı olarak ele alınacaktır. Şimdilik time fonksiyonunu işimizi görecek kadar
inceleyeceğiz. time fonksiyonu 0 argumanıyla çağırıldığında 01.01.1970 tarihinden fonksiyonun
çağırıldığı ana kadar geçen saniye sayısını geri döndürür. Fonksiyonun geri dönüş değeri
derleyicilerin çoğunda long türden bir değerdir. İçinde rasgele sayı üretilecek programda,
srand fonksiyonuna arguman olarak time fonksiyonunun geri dönüş değeri arguman olarak
gönderilirse, program her çalıştığında rasgele sayı üreticisi başka bir tohum değeriyle ilk
değerini alacaktır, böyle progarmın her çalıştırılmasında farklı sayı zinciri üretilecektir.
srand(time(0));
srand fonksiyonunun bu şekilde çağırımı derleyicilerin çoğunda randomize isimli bir makro
olarak tanımlanmıştır. Yukarıdaki fonksiyon çağırımı yerinde bu makro da çağırılabilir. Makrolar
konusunu ileride detaylı olarak inceşeyeceğiz :
randomize();
Yukarıdaki örnek programı her çalıştığında farklı sayı zinciri üretecek hale getirelim:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int k;
srand(time(0));
for (k = 0; k < 10; ++k)
printf("%d ", rand());
return 0;
}
Programlarda bazen belirli bir aralıkta rasgele sayı üretmek isteyebiliriz. Bu durumda mod
operatörü kullanılabilir :

rand() % 2 Yalnızca 0 ya da 1 değerini üretir.
rand() % 6 0 - 5 aralığında rasgele bir değer üretir
rand() % 6 + 1 1 - 6 aralığında rasgele bir değer üretir.
rand() % 6 + 3 5 - 8 aralığında rasgele bir değer üretir.
Karmaşık olasılık problemleri, olsılığa konu olayın bir bilgisayar programı ile simule edilemesi
yoluyla çözülebilir. İyi bir rasgele sayı üreticisi kullanıldığı takdirde, olasılığa konu olay bir
bilgisayar programı ile simule edilir ve olay bilgisayarın işlem yapma hızından faydanlanılarak
yüksek sayılarda tekrar ettirilir. Şüphesiz hesap edilmek istenen olaya ilişkin olasılık değeri,
yapılan tekrar sayısına ve rasgele sayı üreticisinin kalitesine bağlı olacaktır. Aşağıdaki kod yazı
tura atılması olayında tura gelme olasılığını hesap etmektedir.

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#define TIMES 100
#define HEADS 1
int main()
{
long heads_counter = 0;
long k;
for (k = 0; k < TIMES; ++k)
if (rand() % 2 == HEADS)
heads_counter++;
printf("tura gelme olasılığı = %lf", (double) heads_counter / TIMES);
getch();
return 0;
}
Yukarıdaki programı TIMES sembolik sabitinin farklı değerleri için çalıştırdığımızda ekran çıktısı
aşağıdaki şekilde oldu:

#define TIMES 100
tura gelme olasılığı = 0.480000
#define TIMES 500
tura gelme olasılığı = 0.496000
#define TIMES 2500
tura gelme olasılığı = 0.506800
#define TIMES 10000
tura gelme olasılığı = 0.503500
#define TIMES 30000
tura gelme olasılığı = 0.502933
#define TIMES 100000
tura gelme olasılığı = 0.501450
#define TIMES 1000000
tura gelme olasılığı = 0.500198
#define TIMES 10000000
tura gelme olasılığı = 0.500015
#define TIMES 2000000
tura gelme olasılığı = 0.500198
Aşağıdaki main fonksiyonunda uzunlukları 3 - 8 harf arasında değişen ingiliz alfabesindeki
harfler ile oluşturulmuş rasgele 10 kelime ekrana yazdırılmaktadır:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#define TIMES 20
void write_word(void);
int main()
{
int k;
srand(time(0));
for (k = 0; k < TIMES; ++k) {
write_word();
putchar('_);
}
getch();
return 0;
}
void write_word(void)
{
int len = rand() % 6 + 3;
while (len--)
putchar('A' + rand() % 26);
}

Programın ekran çıktısı:
USPFY
KDUP
BUQJB
LMU
PKPBKFA
WQM
NQHPTXL
QCANSTEH
XZU
MNRI
OXUTGISR
XBNG
BYOQ
TFO
MQUCSU
OIHFPJ
BLVD
WDDEM
OHMHJBZY
ALIAQ

Hiç yorum yok:

Yorum Gönder

Her yorum bilgidir. Araştırmaya devam...