教科書の表と同じものです。客の到着間隔とサービスにかかる時間がわかれば、表の全部の欄を埋めることができます。表の仕組みを理解するために、枠になっている欄内に数値を入れて採点してみてください。
[新規問題]をクリックすると到着間隔が乱数で設定されます。サービス時間は5分に固定です。到着時刻、サービス開始時刻、サービス終了時刻、サービス開始までの待ち時間の空欄に数値を入れて、[採点]のボタンを押すと採点されます。
間違ったところを訂正して[採点]のボタンを押し全問正解をめざします。正解したら[送信]のボタンを押してください。
[新規問題]を押せばいつでも新しい問題に替わります。そのときは入力した数値がクリアされますから注意してください。
待ち時間が全員0分になることもあります。その場合は簡単過ぎますから、[新規問題]を押して少なくとも一人は待ち時間が1分以上になる例で100%正解にしてから送信してください。(校内のみの機能)
面倒なのでC言語でプログラムを組んでみます。単純な作業の繰り返しですから、それほど難しくはないのですが、変数の名前を工夫しないと繰り返した時に間違うことがあります。
1: /* 待ち行列 */
2: #include <stdio.h>
3: #include <stdlib.h>
4: #include <time.h>
5: #define DATANUM 100
6:
7: int main()
8: {
9: int kankakumax = 12;
10: int maeTouchaku = 0;
11: int maeShuryou = 0;
12: int kankaku = 0;
13: int i;
14: int touchaku;
15: int kaishi, svjikan, shuryou, machijikan;
16: srand( (unsigned int)time( NULL ) ); /*乱数初期化*/
17: for (i=1 ;DATANUM>=i ;i++){
18: touchaku = maeTouchaku + kankaku;
19: if (touchaku > maeShuryou){
20: kaishi = touchaku;
21: }
22: else {
23: kaishi = maeShuryou;
24: }
25: svjikan = 5;
26: shuryou = kaishi + svjikan;
27: machijikan = kaishi - touchaku;
28: printf ("%5d %5d %8d %8d %5d %8d %5d\n"
29: ,i,kankaku,touchaku,kaishi
30: ,svjikan,shuryou,machijikan);
31: maeTouchaku = touchaku;
32: maeShuryou = shuryou;
33: kankaku = rand()/(double)RAND_MAX*(kankakumax-1)+1;
33: kankaku = rand()/(RAND_MAX+1.0)*kankakumax+1;
34: /*1からkankakumaxの乱数*/
35: }
36: return 0;
37: }
次の人が到着した時に、前の人のサービスが終わっているかどうかで開始時間が変わります。
~/c$ ./k1301
1 0 0 0 5 5 0
2 12 12 12 5 17 0
3 12 24 24 5 29 0
4 3 27 29 5 34 2
5 11 38 38 5 43 0
6 4 42 43 5 48 1
7 10 52 52 5 57 0
8 8 60 60 5 65 0
9 4 64 65 5 70 1
10 4 68 70 5 75 2
11 9 77 77 5 82 0
12 2 79 82 5 87 3
13 3 82 87 5 92 5
14 10 92 92 5 97 0
15 4 96 97 5 102 1
16 2 98 102 5 107 4
17 4 102 107 5 112 5
18 3 105 112 5 117 7
19 2 107 117 5 122 10
20 5 112 122 5 127 10
21 1 113 127 5 132 14
22 2 115 132 5 137 17
23 1 116 137 5 142 21
24 12 128 142 5 147 14
25 7 135 147 5 152 12
26 5 140 152 5 157 12
27 5 145 157 5 162 12
28 5 150 162 5 167 12
29 5 155 167 5 172 12
30 8 163 172 5 177 9
31 1 164 177 5 182 13
32 8 172 182 5 187 10
33 7 179 187 5 192 8
34 1 180 192 5 197 12
35 10 190 197 5 202 7
36 6 196 202 5 207 6
37 4 200 207 5 212 7
38 7 207 212 5 217 5
39 2 209 217 5 222 8
40 8 217 222 5 227 5
41 11 228 228 5 233 0
42 10 238 238 5 243 0
43 9 247 247 5 252 0
44 1 248 252 5 257 4
45 7 255 257 5 262 2
46 1 256 262 5 267 6
47 3 259 267 5 272 8
48 10 269 272 5 277 3
49 3 272 277 5 282 5
50 4 276 282 5 287 6
51 3 279 287 5 292 8
52 4 283 292 5 297 9
53 5 288 297 5 302 9
54 3 291 302 5 307 11
55 3 294 307 5 312 13
56 12 306 312 5 317 6
57 8 314 317 5 322 3
58 8 322 322 5 327 0
59 5 327 327 5 332 0
60 1 328 332 5 337 4
61 3 331 337 5 342 6
62 6 337 342 5 347 5
63 8 345 347 5 352 2
64 10 355 355 5 360 0
65 6 361 361 5 366 0
66 6 367 367 5 372 0
67 3 370 372 5 377 2
68 10 380 380 5 385 0
69 12 392 392 5 397 0
70 4 396 397 5 402 1
71 5 401 402 5 407 1
72 11 412 412 5 417 0
73 2 414 417 5 422 3
74 2 416 422 5 427 6
75 11 427 427 5 432 0
76 8 435 435 5 440 0
77 2 437 440 5 445 3
78 2 439 445 5 450 6
79 6 445 450 5 455 5
80 5 450 455 5 460 5
81 5 455 460 5 465 5
82 9 464 465 5 470 1
83 8 472 472 5 477 0
84 10 482 482 5 487 0
85 12 494 494 5 499 0
86 11 505 505 5 510 0
87 10 515 515 5 520 0
88 7 522 522 5 527 0
89 6 528 528 5 533 0
90 2 530 533 5 538 3
91 8 538 538 5 543 0
92 9 547 547 5 552 0
93 7 554 554 5 559 0
94 3 557 559 5 564 2
95 6 563 564 5 569 1
96 1 564 569 5 574 5
97 8 572 574 5 579 2
98 9 581 581 5 586 0
99 10 591 591 5 596 0
100 8 599 599 5 604 0
教科書にあるサービス時間が3から7の一様乱数である時のプログラムにします。
k1301.c では 25: svjikan = 5; というところがあり、これがサービス時間が5分固定としています。
svjikan = 5;
↓ rand().... を使って3から7の数値になるようにします
↓ 変更はこの1行だけです
svjikan = rand()/????????????????????
ヒントは
/* 1からkankakumaxのとき */kankaku = rand()/(double)RAND_MAX*(kankakumax-1)+1;kankaku = rand()/(RAND_MAX+1.0)*kankakumax+1;
int a = rand()/(RAND_MAX+1.0)*12+1 で a には 1から12までの整数の一様乱数(のひとつ)が入ります。この目的のためには 0以上1未満(つまり 0 ≦ x < 1 )の浮動小数点数の一様乱数が必要です。0以上1以下(つまり 0 ≦ x ≦ 1 )ではうまくいきません。
このために RAND_MAX よりちょっとだけ大きい数で割り算すればいいのですが、RAND_MAX は大きい数なので 1 は十分に小さいだろうと考えているようです。RAND_MAX が 2147483647 の時は 2×10-7程度がちょっとだけの最低の値ですがシステムにより異なるので 1 でも十分に小さいとしようということでしょう
1 でなく 1.0 というのは大切です。1.0 は浮動小数点数として計算しなさいという意味です。RAND_MAXはintで扱える整数の最大値でもありますから、整数のまま 1 を足すと計算の限界を越えてしまいます(オーバーフローといいます)。
| 式 | 値の範囲 | 値の種類 | 解説 |
|---|---|---|---|
| rand() | 0 ≦ a ≦ RAND_MAX | 整数 | RAND_MAXはシステムにより 32767 だったり 2147483647 だったりします |
| rand()/(RAND_MAX+1.0) | 0 ≦ a < 1 | 浮動小数点数 | まず 0 ≦ a < 1 の乱数aを作る |
| rand()/(RAND_MAX+1.0)*12 | 0 ≦ a < 12 | 浮動小数点数 | 1から12の12種類の数が必要なので12を掛ける |
| rand()/(RAND_MAX+1.0)*12+1 | 1 ≦ a < 13 | 浮動小数点数 | 1から12なので1を足す |
| int a = rand()/(RAND_MAX+1.0)*12+1 | 1 ≦ a ≦ 12 | 整数 | intに代入で小数点以下が切り捨てられる。 1 ≦ a < 13 の整数と 1 ≦ a ≦ 12 の整数は同じ意味 |
実行結果は
~/c$ ./k1302
1 0 0 0 6 6 0
2 1 1 6 5 11 5
3 11 12 12 6 18 0
4 10 22 22 5 27 0
5 1 23 27 6 33 4
6 8 31 33 5 38 2
7 7 38 38 5 43 0
8 12 50 50 7 57 0
9 12 62 62 3 65 0
10 1 63 65 4 69 2
11 11 74 74 5 79 0
12 3 77 79 4 83 2
13 7 84 84 4 88 0
14 8 92 92 3 95 0
15 9 101 101 6 107 0
16 9 110 110 3 113 0
17 6 116 116 6 122 0
18 7 123 123 4 127 0
19 6 129 129 4 133 0
20 10 139 139 5 144 0
21 1 140 144 5 149 4
22 2 142 149 6 155 7
23 11 153 155 3 158 2
24 7 160 160 7 167 0
25 3 163 167 5 172 4
26 1 164 172 3 175 8
27 2 166 175 4 179 9
28 5 171 179 6 185 8
29 6 177 185 7 192 8
30 9 186 192 3 195 6
31 8 194 195 5 200 1
32 3 197 200 3 203 3
33 3 200 203 6 209 3
34 5 205 209 6 215 4
35 2 207 215 3 218 8
36 4 211 218 3 221 7
37 8 219 221 4 225 2
38 10 229 229 5 234 0
39 6 235 235 4 239 0
40 5 240 240 6 246 0
41 11 251 251 5 256 0
42 9 260 260 7 267 0
43 8 268 268 3 271 0
44 8 276 276 3 279 0
45 1 277 279 4 283 2
46 4 281 283 6 289 2
47 10 291 291 5 296 0
48 10 301 301 7 308 0
49 4 305 308 3 311 3
50 9 314 314 4 318 0
51 5 319 319 7 326 0
52 8 327 327 3 330 0
53 5 332 332 4 336 0
54 7 339 339 7 346 0
55 9 348 348 7 355 0
56 6 354 355 5 360 1
57 4 358 360 3 363 2
58 7 365 365 7 372 0
59 4 369 372 3 375 3
60 1 370 375 4 379 5
61 5 375 379 4 383 4
62 12 387 387 3 390 0
63 11 398 398 6 404 0
64 2 400 404 3 407 4
65 12 412 412 7 419 0
66 7 419 419 4 423 0
67 11 430 430 3 433 0
68 5 435 435 4 439 0
69 7 442 442 7 449 0
70 1 443 449 4 453 6
71 10 453 453 5 458 0
72 10 463 463 3 466 0
73 9 472 472 4 476 0
74 1 473 476 7 483 3
75 5 478 483 3 486 5
76 3 481 486 6 492 5
77 6 487 492 3 495 5
78 11 498 498 4 502 0
79 12 510 510 3 513 0
80 6 516 516 7 523 0
81 11 527 527 3 530 0
82 3 530 530 6 536 0
83 3 533 536 5 541 3
84 12 545 545 6 551 0
85 6 551 551 7 558 0
86 11 562 562 3 565 0
87 6 568 568 6 574 0
88 4 572 574 3 577 2
89 12 584 584 4 588 0
90 1 585 588 4 592 3
91 5 590 592 4 596 2
92 1 591 596 7 603 5
93 6 597 603 7 610 6
94 2 599 610 4 614 11
95 12 611 614 6 620 3
96 4 615 620 7 627 5
97 8 623 627 5 632 4
98 8 631 632 7 639 1
99 1 632 639 5 644 7
100 7 639 644 5 649 5
rand()/(double)RAND_MAX*11+1 を出すまでは問題ないのですが、int の変数に代入すると切り捨てされてしまい、最後の整数になる値の範囲が極小になってしまいます。
| 式 | 値の範囲 | 値の種類 | 解説 | |
|---|---|---|---|---|
| ○ | rand() | 0 ≦ a ≦ RAND_MAX | 整数 | RAND_MAXの値はシステムにより異なる |
| ○ | rand()/(double)RAND_MAX | 0 ≦ a ≦ 1 | 浮動小数点数 | (double)は浮動小数点数にして計算するということ。 intのままでは0か1のどちらかになってしまう |
| ○ | rand()/(double)RAND_MAX*11 | 0 ≦ a ≦ 11 | 浮動小数点数 | |
| ○ | rand()/(double)RAND_MAX*11+1 | 1 ≦ a ≦ 12 | 浮動小数点数 | ここまでは問題ない |
| × | int a = rand()/(double)RAND_MAX*11+1 | 1 ≦ a ≦ 12 | 整数 | ≦ 12ですが、12がほとんど出ません。、 12.00 が最大値で 12.xx なる小数が全くないからです |