乱数・数学ライブラリ - 早稲田大学

C プログラミング 入門
第8回
— 乱数・数学ライブラリ —
早稲田大学
創造理工学部
–建築・経営・資源–
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
1 / 23
前回の復習
配列
宣言
添字演算子「[ ]」
添字の有効範囲
初期化
多次元配列
#define
定義と使用法
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
2 / 23
前回の復習:配列
配列(int 型の変数を 100 個用意する場合)
/*配列宣言*/
int Data[100];
同じ扱いの変数が複数必要なとき,配列を使う
一つ一つの変数は,通し番号 (添え字)をつけて区別
添字演算子「[ ]」を使い,中に番号を指定する
番号は 0 から始まり,100-1=99 で終わる.
Data[0] から Data[99] までの 100 個の変数が用意される
代入に関しては,今までと同様
配列は宣言と同時に初期化することが可能
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
3 / 23
前回の復習:マクロ定義 #define
マクロ定義 (#define 文字列 1 文字列 2)
文字列1を文字列2で置き換える
#define SIZE 3
この行以降は,
「SIZE」と書くと「3」だと扱われる
マクロ定義には注釈を書く(推奨)
定数に対して名前が与えられ,プログラムが読みやすい
慣習として,マクロ名は大文字で書く
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
4 / 23
第 7 回小レポート課題
問題:次のファイルを作成し,Course N@vi より提出せよ
配列 A[3][4] に以下のような数字を入れ,それを転置させたものを表示す
るプログラムを作れ.表示は以下のようにする.
A=
1 2
5 6
9 10
A^t=
1 5
2 6
3 7
4 8
3 4
7 8
11 12
9
10
11
12
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
5 / 23
第 7 回小レポートの解答例(tenchi.c)
#include<stdio.h>
#define gyou 3
#define retsu 4
int main(void){
int i,j;
int A[gyou][retsu];
/* A[3][4] と宣言 */
for(i=0;i<gyou;i++){
for(j=0;j<retsu;j++){
A[i][j] = retsu*i + j + 1;
}
}
printf("A=\n");
for(i=0;i<gyou;i++){
for(j=0;j<retsu;j++){
printf("%3d",A[i][j]);
}
printf("\n");
}
.
.
.
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
/* 値の代入 */
/* A の表示 */
6 / 23
第 7 回小レポートの解答例(tenchi.c)
..
.
printf("A^t=\n");
for(i=0;i<retsu;i++){
for(j=0;j<gyou;j++){
printf("%3d",A[j][i]);
}
printf("\n");
}
return 0;
/* A^t の表示 */
}
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
7 / 23
本日の目標
ヘッダファイルのインクルード(#include)を理解する.
擬似乱数が使える.
#include
初期化
整数乱数
実数乱数
数学ライブラリが使える
数学関数・定数
コンパイル方法(gcc ファイル名 -lm)
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
8 / 23
ヘッダファイルのインクルード(#include)
プログラムの先頭で「 #include<stdio.h>」と記述してきた
printf 関数や scanf 関数を使用するためにインクルード(読み込み)
していた
C 言語には,関数を集めた標準ヘッダファイルが準備されている
プログラム中で使用する関数に応じて,必要な標準ヘッダファイル
をインクルードする必要がある
主な標準ヘッダファイルは次の通り:
stdio.h: printf, scanf 等(入出力関数)
stdlib.h: rand, srand, exit, malloc 等
math.h: exp, aqrt, sin, cos 等(数学関数)
string.h: strcpy, strlen 等(文字列処理関数)
time.h: time 等(時刻,日付に関する関数)
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
9 / 23
擬似乱数
プログラムで (擬似) 乱数を利用する
「(i∗83+12)%101」として,一見ランダムな点数を与えたが,もう
少し複雑な式を用いた乱数を使う
✓
乱数とは
✏
それぞれの数字が同じ確率で現れるように並べられた数字の列
のことである
C 言語のプログラムでは,rand 関数を使う.この関数は乱数を
計算で求めている.各数字が正確に同じ確率で現れることはな
いので,擬似乱数とも呼ばれる
✒
rand 関数はある値を元に乱数を計算し,2 回目以降は前回の乱
数値を元に計算するので,最初のある値が同じであれば,同じ
乱数の列が現れる
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
✑
10 / 23
擬似乱数
使用方法:必要なヘッダファイルを include する
#include <time.h>
#include <stdlib.h>
/* time 関数を使う場合に必要 */
/* これは必要 */
現在時刻を使って乱数を初期化する
srand((unsigned)time(NULL)); /* 乱数系列を初期化 */
実行させる度に同じ乱数を得たい場合は,これを省略するか
「srand(56);」などと固定値を指定
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
11 / 23
擬似乱数(規則性がかなり残っている)
0∼RAND _ MAX の整数乱数を得る
a = rand();
(RAND_MAX は, stdlib.h の中で 0x7fffffff と定義されている)
0以上1未満の実数乱数を得る
a = rand()/ (RAND_MAX +1.0);
0以上 N 未満の整数乱数を得る
a = (int) (rand()/(RAND_MAX +1.0)*N);
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
12 / 23
擬似乱数使用例
✓
さいころの目(saikoro.c)
✏
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(void){
int a;
srand((unsigned) time(NULL));
a = (int) (rand()/(RAND_MAX+1.0)*6);
printf("Result is %d. Yn", a+1);
return 0;
}
✒
✑
→ 0∼5までの乱数を作り,最後に1を足せばよい.
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
13 / 23
演習
課題1:今の運勢を表示するプログラムを作れ.
下の確率で右のメッセージを表示するプログラムを作れ.
確率
メッセージ
30 %
Very lucky
60 %
lucky
10 %
Not lucky
何回も実行させて,だいたい上記確率で表示されることを確かめよ
time() は 1970 年 1 月 1 日 0 時 0 分(標準時)からの経過秒数を返す
ため,1 秒以内に何度も実行すると,同じ数字で乱数を初期化する
ことになり,結果も同じになってしまう
結果を日ごとに変えたい場合は,次のようにする
srand((unsigned)time(NULL)/(60*60*24));
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
14 / 23
課題1のヒント
#include,乱数の初期化を忘れずに
判定は if 文を使う(例えば)
:
if(a<0.3)
else if(a<0.9)
else
第 8 回— 乱数・数学ライブラリ —
printf("...")
printf("...")
printf("...")
C プログラミング 入門
15 / 23
数学ライブラリ
プログラムで sin や log などの数学関数,π などの数学定数を利用す
ることができる.
数学関数や数学定数を使うには
1
ヘッダファイルを include する
#include <math.h>
2
「-lm」(エル・エム)とつけてコンパイル
$ gcc ファイル名 -lm
これを忘れると「:undefined reference to ∼」とエラー
3
プログラムの中で数学関数を使用する(10 の自然対数)
a= log(10.0);
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
16 / 23
数学ライブラリ(参考)
数学関数
使用法
fabs(x)
log(x)
pow(x,y)
floor(x)
cos(x)
sin(x)
tan(x)
atan2(y,x)
sinh(x)
意味
絶対値
自然対数
xのy乗
(小数点以下)切り下げ
cos
sin
tan
arctan(y/x)
sinh
使用法
exp(x)
log10(x)
sqrt(x)
ceil(x)
acos(x)
asin(x)
atan(x)
cosh(x)
tanh(x)
意味
指数
常用対数
平方根
切り上げ
arccos
arcsin
arctan
cosh
tanh
数学定数
使用法
M_PI
M_E
第 8 回— 乱数・数学ライブラリ —
意味
π
e
使用法
M_SQRT2
M_LN10
C プログラミング 入門
意味
2の平方根
loge 10
17 / 23
演習
課題2:以下のプログラムを作成し実行せよ
0◦ ∼180◦ まで 10◦ ごとに sin(x) の値を表示するプログラム.
数学ライブラリの sin 関数は,入力値の単位がラジアン.
角度, sin(x) の値の順で表示させるようにする.
x の値は角度をラジアンに変換した値.
表示例:
ang=0, sin(0)=0.00
ang=10, sin(0.17)=0.17
ang=20, sin(?)=?
..
.
ang=180, sin(3.14)=0.00
π は数学定数 M PI として定義されている
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
18 / 23
課題2のヒント
math.h を用いる
変数の定義:角度 x,ラジアン rad
繰り返しは,for 文か while 文:
while(x<=180){
実行させたい命令
}
角度 x からラジアン rad への変換:
rad = x * M PI / 180.0;
表示は printf:
printf("ang=%.0f, sin(%.2f)=%.2f Y n",x, rad, sin(rad));
コンパイルの際「-lm」を忘れずに
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
19 / 23
第 8 回小レポート
レポート提出について
次のプログラムを作成せよ
ソースファイルは「08-学生番号.c」とせよ
タイトルは「第 8 回小レポート」とする
本文には(必要があれば)講義内容や成績に対する質問を書くこと
課題を提出するときには課題のソースファイルを添付せよ
提出期限:授業中に指示
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
20 / 23
第 8 回 小レポート
課題:乱数を用いて,定積分の値を近似的に求めよ.
0以上1未満の乱数 x, y を入力された回数だけ繰り返し,
y < sin(πx) となった割合 r を計算する
∫ 1
2
この割合は,
sin πx = に収束する
π
0
求めた値 r を表示し,2/π との語差 (Error) を表示せよ
表示は以下のようにする:
How many trials? 1000【Enter】
Result is 0.652000 (Error: -0.015380)
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
21 / 23
第 8 回 小レポート(ヒント)
ヘッダファイルの include を忘れずに(time.h,stdlib.h,math.h)
-lm で数学ライブラリをリンクするのを忘れずに
(x, y) の座標にそれぞれに対して 0∼1 の乱数を対応させる
(x, y) の組を乱数により N 回発生させると,1 × 1 の正方形の中に N
個の点をばらまくことに相当する
求めたい割合:
条件を満たした点の数
点の数 N
点の数のカウントは int 型で行うこと
割合を計算するときにキャスト演算子を忘れずに
1
0
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
1
22 / 23
第 8 回 小レポート(追加課題)
追加課題:乱数を用いて,以下を求めよ.
正方形とそれに内接する 4 分の 1 円 ( 扇形 )を考える.この正方
形の中にランダムに点を落としたとき,正方形内の点と円内に落ち
た点との比を考え円周率を求めよ.表示は小レポート課題と同じよ
うに,回数を入力し,結果と,円周率(M PI)との誤差を出力せよ.
(できたら加点)
ソースファイルは「08-02-学生番号.c」とせよ
第 8 回— 乱数・数学ライブラリ —
C プログラミング 入門
23 / 23