亂數原型

#include <stdlib.h>
int rand(void); //取得亂數
void srand(unsigned seed); //設定亂數種子

【亂數的概念】
1.假設有一組數列為 0、1、2、...、9。
2.假設種子為 8。
3.電腦程式啟動執行時,第一次叫用此數列的數字為種子加 7,並除以10取餘數。因此第一次數字為 (8+7)%10=5。
4.第二次叫用時,以第一次數字加 7,並除以10取餘數。
   因此第二次數字為 (5+7)%10=2。
5.爾後每次叫用數字時以上列規則執行,則新的數列變成5、2、9、6、3、0、7、4、1、8 (以下循環),感覺上數字順序就被打亂了,因此稱為亂數數列。
6.好的亂數演算法,不會讓使用者看出每一個數字演變的規則,也不容易看出循環規則。
7.為了讓亂數每次起點可以改變,使用者可以定義種子。
以上為例:若改變種子為 4,則亂數數列變成:
(4+7)%10=1、(1+7)%10=852963074
8.為了讓亂數可以限制數字範圍,使用者可以將亂數數列除以某一母數取餘數得到新的亂數數列。
以上為例:若定義母數為 6,則原亂數數列為 5、2、9、6、3、0、7、4、1、8,會變成 5%6=5、2%6=2、9%6=3、6%6=0、3%6=3、0%6=0、7%6=1、4%6=4、1%6=1、8%6=2 (以下循環)。

【亂數實驗】
#include <stdio.h>
#include <stdlib.h>
void main()
{
   int a,i;
   for(i=0;i<10;i++){
      a=rand()%10;
      printf("%d\n", a);
   }
}


1.請複製上面程式,並執行它,且觀察數字變化。
2.多執行幾次,並觀察數字出現順序是否改變。
3.將程式 a=rand()%10; 改成 a=rand()%6; 並觀察數字變化。

將程式適當修改成如下:
#include <stdio.h>
#include <stdlib.h>
void main()
{
   int a,i;
   srand(5);
   for(i=0;i<10;i++){
      a=rand()%10;
      printf("%d\n", a);
   }
}

1.多執行幾次,並觀察數字出現順序是否改變。
2.將 srand(5); 改成 srand(6);,且多執行幾次,並觀察數字出現順序是否改變。

將程式再適當修改成如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void main()
{
   int a,i;
   srand(time(NULL));
   for(i=0;i<10;i++){
      a=rand()%10;
      printf("%d\n", a);
   }
}

多執行幾次,並觀察數字出現順序是否改變。

【說明】
time 原型如下:
time_t time(time_t *timer); //取得系統目前秒數。
當指標指向 NULL 時,time 會傳回電腦目前的秒數。

【亂數範圍與起點設定】
1.假設起點為 s,範圍為 r,間隔為 w,則亂數公式為:
   (rand()%r)*w+s

範例:
亂數數列為 7、10、13、16、19 (共 5 個)
由上數列可知 起點為 7,間隔 3 (10-7),範圍 5
則程式碼為 (rand()%5)*3+7

若間隔無規則可言,則必須使用陣列存取。
範例:
亂數數列為 7、22、19、-100、3、29 (共 6 個)
則程式碼為:
int x[]={7, 22, 19, -100, 3, 29};
int y;
y=x[(rand()%6];

【亂數命中機率分配設定】
假設 某亂數數列及機率分配如下:
數字
機率
1 1/1000
2 7/100
3 3/10
4 1-(1/1000+7/100+3/10)

由上可知最大範圍為 1000
每個數字依照 1000 個配置數量如下:
數字
數量
範圍
1
1 0
2
70 1 至 70
3
300 71 至 370
4
1000-(1+70+300)=629 370 至 999


程式碼
y=rand()%1000; //產生數字 0 至 999
if(y==0)
   printf("1\n");
else if((y>=1)&&(y<=70))
   printf("2\n");
else if((y>=71)&&(y<=370))
   printf("3\n");
else
   printf("4\n");