توليد اعداد تصادفی

يکی از کاربردهای اساسی کامپيوتر، استفاده از آن در کارهای شبيه سازی می باشد. در اينجا به بررسی نحوه توليد اعداد تصادفی می پردازيم. اعداد تصادفی در مسائل شبيه سازی کاربرد فراوانی دارند، به عنوان مثال شبيه سازی پرتاب سکه، پرتاب تاس و مسائلی از اين قبيل.

برای توليد اعداد تصادفی زبان ++C تابعی با نام rand() را که در فايل کتابخانه ای stdlib.h قرار دارد، در اختيار ما گذاشته است. به عنوان مثال دستور زير :

i = rand();

يک عدد تصادفی بين 1 تا 32767 را در متغير i قرار می دهد . تابع rand() اعداد را با احتمال مساوی در اين بازه انتخاب می کند پس شانس انتخاب هر عددی در اين بازه با اعداد ديگر برابر است.

معمولاً بازه اعدادی که توسط تابع rand توليد می شود، با آنچه که مورد نياز ماست متفاوت می باشد. به عنوان مثال برای شبيه سازی پرتاب سکه به دو عدد تصادفی و برای تاس به شش عدد تصادفی نياز داريم. فرض کنيد که می خواهيد عدد 31250 را به عددی بين 1 تا 6 تبديل کنيد. چه راه کاری را در نظر می گيريد؟ راهی که برای اين تبديل وجود دارد استفاده از باقيمانده صحيح می باشد، همانطور که می دانيد باقيمانده صحيح تقسيم هر عددی بر 6 يکی از اعداد 0 تا 5 می باشد. پس با اضافه کردن 1 واحد به باقيمانده ، عددی بين 1 تا 6 خواهيم داشت. به عنوان مثال در کادر زير عددی بين 1 تا 32767 وارد کنيد و با کليک بر روی دکمه محاسبه خروجی ، نتيجه محاسبه را ببينيد :

 

Top of Form

a=
a%6+1=

Bottom of Form

حال اگر به جای متغير a ، تابع rand() را قرار دهيم عبارت rand()%6+1 عددی تصادفی بين 1 تا 6 به ما می دهد به طور کلی برای بدست آوردن عددی تصادفی در بازه [a,b] می توانيم از فرمول زير استفاده کنيم.

rand()%(b-a+1)+a

به عنوان مثال خروجی قطعه برنامه زير عدد صحيحی در بازه [20,100] می باشد.

int a = 20 , b = 100;

cout<< rand()%(b-a+1)+a;

برنامه زير 20 عدد تصادفی بين 1 تا 6 را ايجاد می کند. که اين برنامه را می توان 20 بار پرتاب يک تاس در  نظر گرفت :

#include <iostream.h>

#include <stdlib.h>

 

int main()

{

   for (int i = 1; i<= 20; i++ )

    {

     cout << rand() % 6 + 1<<"\t";

 

     if ( i % 5 == 0 )

        cout << endl;

    }

   return 0;

}

خروجی برنامه فوق به صورت زير می باشد :

5       5       3       5       5

2       4       2       5       5

5       3       2       2       1

5       1       4       6       4

يک بار ديگر برنامه فوق را اجرا کنيد و خروجی را مجدداً بررسی کنيد. خواهيد ديد خروجی دقيقاً همان اعداد قبلی می باشد. خروجی تابع rand() اعداد تصادفی می باشد ولی با اجرای دوباره برنامه همان اعداد مجدداً به همان ترتيب قبلی تکرار می شوند. اين تکرار يکی از قابليتهای تابع می باشد ودر اشکال زدايی برنامه کاربرد دارد.

اگر بخواهيم که تابع rand() اعداد کاملاً تصادفی ايجاد کند بايد از تابع srand() استفاده کنيم. اين تابع ورودی از نوع اعداد صحيح بدون علامت می گيرد و باعث تصادفی شدن تابع rand() بر اساس مقدار ورودی تابع srand() می شود. تابعsrand() نيز در فايل کتابخانه ای stdlib.h قرار دارد. در برنامه زير به نحوه استفاده از تابع srand() پی خواهيد برد.

#include <iostream.h>

#include <stdlib.h>

 

int main()

{

  unsigned int num;

 

  cout<<"Enter a number: ";

  cin>>num;

 

  srand(num);

 

  for (int i = 1; i<= 20; i++ )

   {

    cout << rand() % 6 + 1<<"\t";

 

    if ( i % 5 == 0 )

      cout << endl;

   }

  return 0;

}

خروجی برنامه به صورت زير می باشد.

Enter a number: 251

3       4       1       4       6

6       4       6       2       5

5       3       1       4       5

1       6       6       6       1

Enter a number: 350

1       4       3       4       1

2       6       2       6       2

4       2       5       3       5

4       4       5       2       3

Enter a number: 251

3       4       1       4       6

6       4       6       2       5

5       3       1       4       5

1       6       6       6       1

همانطور که می بينيد بر اساس ورودی های مختلف خروجی نيز تغيير می کند. توجه داشته باشيد که ورودی های يکسان خروجی های يکسانی دارند.

اگر بخواهيم بدون نياز به وارد کردن عددی توسط کاربر، اعداد تصادفی داشته باشيم می توانيم از تابع time که در فايل کتابخانه ای time.h قرار دارد استفاده کنيم . تابع time ساعت کامپيوتر را می خواند و زمان را بر حسب ثانيه بر می گرداند ، به اين ترتيب دستور زير:

srand(time(0));

باعث می شود که تابع rand() در هر بار اجرای برنامه اعداد متفاوتی را ايجاد کند. اگر برنامه فوق را به صورت زير باز نويسی کنيم با هر بار اجرای برنامه اعداد تصادفی متفاوتی خواهيم داشت.

#include <iostream.h>

#include <stdlib.h>

#include <time.h>

 

int main()

{

  srand(time(0));

 

  for (int i = 1; i<= 20; i++ )

   {

    cout << rand() % 6 + 1<<"\t";

   

    if ( i % 5 == 0 )

      cout << endl;

   }

  return 0;

}

مثال : برنامه ای بنويسيد که پرتاب سکه ای را شبيه سازی کند ، بدين صورت که سکه را 2000 بار پرتاب کند و دفعات رو يا پشت آمدن سکه را چاپ کند.

#include <iostream.h>

#include <stdlib.h>

#include <time.h>

 

int main()

{

  int back=0,front=0,face;

 

  srand(time(0));

 

  for (int i = 1; i<= 2000; i++ )

    {

      face=rand()%2+1;

      switch(face)

        {

          case 1:

            ++back;

            break;

          case 2:

            ++front;

            break;

          default:

            cout<<"Error!";

        }

    }

 

  cout<<"Front: "<< front<<endl;

  cout<<"Back : "<< back<<endl;

 

  return 0;

}

 

  

نوع داده ای enum

enum يک نوع داده ای تعريف شده توسط برنامه نويس را که به آن نوع داده شمارش می گويند، ايجاد می کند. نحوه ايجاد يک نوع داده شمارش به صورت زير می باشد.

enum {ثابت n و ... و ثابت 2 و ثابت 1} نام نوع داده

اين دستور به ترتيب در ثابت 1 ، ثابت 2 و ... و ثابتn اعداد صحيح متوالی 0 تا n را قرار می دهد . به صورت پيش فرض مقداردهی متغيرها در اين دستور از صفر شروع می شود.

enum TrueFalse {FALSE , TRUE}

دستور فوق به ثابت FALSE ، عدد صفر و به ثابت TRUE عدد 1 را تخصيص می دهد. حال اگر بخواهيم مقداردهی از عددی غير از صفر شروع شود بايد عدد مورد نظر را مشخص کنيم :

enum Days {SAT = 1, SUN, MON, TUE, WED, THU, FRI}

دستور فوق به روزهای هفته به ترتيب اعداد 1 تا 7 را نسبت می دهد. توصيه می شود که نام ثابت های شمارشی را با حروف بزرگ بنويسيد ، بدين صورت اين ثابتها با متغيرهای برنامه ، اشتباه نمی شوند. ضمناً enum را در ابتدای برنامه به کار ببريد.

در حقيقت اين نوع داده به هر يک از موارد ليستی از اعداد نامی را نسبت می دهد. به عنوان نمونه در مثال روزهای هفته هر يک از اعداد 1 تا 7 را با يکی از روزهای هفته نام گذاری کرديم.

مقدار دهی موارد ليست به صورت های مختلف امکان پذير می باشد.

enum Days { MON, TUE, WED, THU, FRI, SAT , SUN = 0}

دستور فوق SUN را با عدد صفر و SAT را با عدد 1- و ... و MON را با عدد   -6 مقدار دهی می کند.

enum Colors {BLACK = 2, GREEN = 4, RED = 3,

             BLUE = 5, GRAY,WHITE = 0}

در دستور فوق هر يک از موارد با عدد نسبت داده شده مقدار دهی می شوند و GRAY با عدد 6 مقدار دهی می شود چون بعد از BLUE = 5 آمده است.

به محض ساخته شدن ليست ، نوع داده نوشته شده توسط برنامه نويس قابل استفاده می گردد و می توان متغيرهايی را از نوع داده نوشته شده توسط برنامه نويس به همان شيوه ای که ساير متغيرها را تعريف می کرديم، تعريف کرد. به عنوان مثال :

TrueFalse  tf1,tf2;

Days       day1, day2 = SUN;

Colors     color1 = BLACK , color2 = GRAY;

همچنين متغيرها را می توان هنگام ايجاد نوع داده، تعريف کرد. به عنوان مثال :

TrueFalse {FALSE, TRUE} tf1 ,tf2;

نکته : تبديل داده ای از نوع enum به عدد صحيح مجاز می باشد ولی بر عکس اين عمل غير مجاز است. به عنوان مثال :

enum MyEnum {ALPHA, BETA, GAMMA};

int   i = BETA;

int   j = 3+GAMMA;

دستورات فوق مجاز می باشند، و اين دستورات عدد 1 را در i و 5 را در j قرار می دهند.

enum MyEnum {ALPHA, BETA, GAMMA};

MyEnum  x = 2;

MyEnum  y = 123;

ولی دستورات فوق غير مجاز می باشند. البته بعضی از کامپايلرها اين موضوع را ناديده می گيرند و تنها يک پيغام اخطار می دهند ولی توصيه می شود که برای پيشگيری از وقوع خطاهای منطقی در برنامه از به کار بردن دستوراتی مانند کدهای فوق خودداری کنيد.

برنامه زير نحوه کاربرد نوع داده enum را نشان می دهد.

#include <iostream.h>

int main()

{

  enum PizzaSize{SMALL,MEDIUM,LARGE,EXTRALARGE};

  PizzaSize size;

  size=LARGE;

 

  cout<<"The small pizza has a value of "<<SMALL;

  cout<<"\nThe medium pizza has a value of "<<MEDIUM;

  cout<<"\nThe large pizza has a value of "<<size;

 

  return 0;

}

خروجی برنامه به صورت زير می باشد:

The small pizza has a value of 0

The medium pizza has a value of 1

The large pizza has a value of 2