ページ 11

乱数について

Posted: 2014年1月02日(木) 10:16
by Sera
皆さん、新年明けましておめでとうございますヽ(*´∀`)ノ

早速なんですが、乱数に関する質問です。(`・ω・´)

先日、あるC言語に関する書籍を買ったのですが、その中に、

1から999までを指定するにはsrand関数で乱数を初期化してあまりを出すためにrand % xにすればいい。

などと意味のわからないことばかりでした。。。

サンプルソースを一応書いておきます

コード:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    int i;
    srand( (unsigned int)time(NULL) );
    for(i = 0; i < 10;i++){
        printf("%d\n",rand()%1000 + 1);
    }
    return 0;
}
もうぶっちゃけて言うとほとんど理解できていないんですが
srand( (unsigned int)time(NULL) );

rand()%1000 + 1
の意味をよかったら詳しく教えてください・゚・(ノД`)・゚・

Re: 乱数について

Posted: 2014年1月02日(木) 10:22
by softya(ソフト屋)
あけまして、おめでとうございます。

塊で考えているようなので、もっと分解して考えてみましょうか。
理解するためには分解しないといけないですよ。

と言うことで逆質問してみます。
これは何でしょうか? 説明してみてください。
(1) srand
(2) time(NULL)
(3) rand()
(4) %1000
です。

Re: 乱数について

Posted: 2014年1月02日(木) 10:24
by Sera
softya(ソフト屋) さんが書きました:あけまして、おめでとうございます。

塊で考えているようなので、もっと分解して考えてみましょうか。
理解するためには分解しないといけないですよ。

と言うことで逆質問してみます。
これは何でしょうか? 説明してみてください。
(1) srand
(2) time(NULL)
(3) rand()
(4) %1000
です。
えっと、、、
(1)srand
は、、、あれ、わかんない(;´Д`)
(2)time(NULL)
モ、、、、わからない(´;ω;`)
(3)rand()
これは、、乱数の呼び出しですか???
(4)
これは1000で割ったときの余りを出す計算ですか??

Re: 乱数について

Posted: 2014年1月02日(木) 10:25
by みけCAT
☆をつけた関数の説明文は苦Cからの引用です。

srand( (unsigned int)time(NULL) );
☆srand : 乱数系列の初期値を与える。
☆time : 現在の時刻を基準時刻からの経過秒数で返す。

乱数系列を現在の時刻に指定するので、(1秒以上間隔をあけて起動すれば)毎回違う乱数が出るようになることを想定しています。

rand()%1000 + 1
☆rand : 乱数を得る。
乱数の値を1000で割ったあまりに1を足しているので、RAND_MAXが十分大きければ[1,1000]の整数の乱数が得られるはずです。
ただし、処理系によっては単純に余りを取ると乱数の精度が悪いかもしれません。

Re: 乱数について

Posted: 2014年1月02日(木) 10:29
by Sera
みけCAT さんが書きました:☆をつけた関数の説明文は苦Cからの引用です。

srand( (unsigned int)time(NULL) );
☆srand : 乱数系列の初期値を与える。
☆time : 現在の時刻を基準時刻からの経過秒数で返す。

乱数系列を現在の時刻に指定するので、(1秒以上間隔をあけて起動すれば)毎回違う乱数が出るようになることを想定しています。

rand()%1000 + 1
☆rand : 乱数を得る。
乱数の値を1000で割ったあまりに1を足しているので、RAND_MAXが十分大きければ[1,1000]の整数の乱数が得られるはずです。
ただし、処理系によっては単純に余りを取ると乱数の精度が悪いかもしれません。
ムムム、、、
srandとtimeについてはなんとなくは理解できたかも(;^ω^)
でも、unsigned intとNULLの意味がイマイチ、、、

randについては、訳がわかりません(´;ω;`)
1000で割って余りに1を足すと1~999の値になるんですかね。。?

Re: 乱数について

Posted: 2014年1月02日(木) 10:30
by softya(ソフト屋)
googleさんで検索してみましたか? 便利ですよgoogleさん。

とりあえず、C言語の標準ライブラリが説明されているサイトを紹介しておきます。
「ライブラリ関数一覧」
http://www9.plala.or.jp/sgwr-t/lib/libtop.html
(3) 確かにそうですが、もう少し正確にお願いします。
(4) ご自分でも書いてますが割った余りを出します。1000で割ったあまりの値の範囲を書いてみてください。

Re: 乱数について

Posted: 2014年1月02日(木) 10:31
by みけCAT
unsigned int : 符号なし整数型
NULL : どこも指していないポインタ
Sera さんが書きました:1000で割って余りに1を足すと1~999の値になるんですかね。。?
少なくとも、「一般的な」割り算と足し算の定義では1~999の値だけにはなりません。
乱数の質が悪ければなるかもしれません。

Re: 乱数について

Posted: 2014年1月02日(木) 10:42
by みけCAT
自分が前に書いたsrand((unsigned int)time(NULL));の説明です。
N次元の半径1の体積を求める c++ • C言語交流フォーラム ~ mixC++ ~

Re: 乱数について

Posted: 2014年1月02日(木) 11:03
by Sera
softya(ソフト屋) さんが書きました:googleさんで検索してみましたか? 便利ですよgoogleさん。

とりあえず、C言語の標準ライブラリが説明されているサイトを紹介しておきます。
「ライブラリ関数一覧」
http://www9.plala.or.jp/sgwr-t/lib/libtop.html
(3) 確かにそうですが、もう少し正確にお願いします。
(4) ご自分でも書いてますが割った余りを出します。1000で割ったあまりの値の範囲を書いてみてください。
googleさんで見てみました!(`・ω・´)
srandはコンピュータ内で決まっている乱数の発生系列を変更させるってことですね!

time(NULL)はやっぱり理解できませぬ。。。

(3)は
コンピュータ内のある発生系列に従って文字を渡すってことでしょうか。
(4)は、、、
余りの値の範囲は割ったかず以下だから、、、999ですね!

Re: 乱数について

Posted: 2014年1月02日(木) 11:04
by Sera
みけCAT さんが書きました:unsigned int : 符号なし整数型
NULL : どこも指していないポインタ
Sera さんが書きました:1000で割って余りに1を足すと1~999の値になるんですかね。。?
少なくとも、「一般的な」割り算と足し算の定義では1~999の値だけにはなりません。
乱数の質が悪ければなるかもしれません。
符号なし整数型っていうのは要するに正数ってことでいいんでしょうか??

どこも指していないポインタというのはどいういった意味なんでしょうか。。。

Re: 乱数について

Posted: 2014年1月02日(木) 11:11
by みけCAT
Sera さんが書きました:time(NULL)はやっぱり理解できませぬ。。。
この値だけを出力してみるといいかもしれません。

コード:

#include <stdio.h>
#include <time.h>

int main(void) {
    printf("%u\n",(unsigned int)time(NULL));
    return 0;
}
Sera さんが書きました:符号なし整数型っていうのは要するに正数ってことでいいんでしょうか??
非負整数ですね。
32ビットなら、0以上4294967295以下の整数を表現できます。
Sera さんが書きました:どこも指していないポインタというのはどいういった意味なんでしょうか。。。
「無効」を表現しているポインタです。
今回の場合、時刻を変数に格納せず、戻り値だけ返せばいい、という意味です。

Re: 乱数について

Posted: 2014年1月02日(木) 11:20
by softya(ソフト屋)
>(3)は
>コンピュータ内のある発生系列に従って文字を渡すってことでしょうか。

文字は出てきませんよ。数値です。
C言語では数値と文字と文字列の扱いに注意して下さい。

>(4)は、、、
>余りの値の範囲は割ったかず以下だから、、、999ですね!

範囲ですので始まりもお願いします。

Re: 乱数について

Posted: 2014年1月02日(木) 11:25
by みけCAT
Sera さんが書きました:(4)は、、、
余りの値の範囲は割ったかず以下だから、、、999ですね!
間違っている気がします。
割ったかず「以下」ではないのではないですか?

Re: 乱数について

Posted: 2014年1月02日(木) 13:55
by Sera
みけCAT さんが書きました:
Sera さんが書きました:(4)は、、、
余りの値の範囲は割ったかず以下だから、、、999ですね!
間違っている気がします。
割ったかず「以下」ではないのではないですか?
割ったかずより下ですね!笑

Re: 乱数について

Posted: 2014年1月02日(木) 13:55
by Sera
softya(ソフト屋) さんが書きました:>(3)は
>コンピュータ内のある発生系列に従って文字を渡すってことでしょうか。

文字は出てきませんよ。数値です。
C言語では数値と文字と文字列の扱いに注意して下さい。

>(4)は、、、
>余りの値の範囲は割ったかず以下だから、、、999ですね!

範囲ですので始まりもお願いします。
始まりは、、、
+1しているから1~999でしょうか?

Re: 乱数について

Posted: 2014年1月02日(木) 13:58
by みけCAT
Sera さんが書きました:始まりは、、、
+1しているから1~999でしょうか?
違いますね。(範囲は1~999ではないです)
何に+1しましたか?

Re: 乱数について

Posted: 2014年1月02日(木) 13:59
by Sera
みけCAT さんが書きました:
Sera さんが書きました:始まりは、、、
+1しているから1~999でしょうか?
違いますね。(範囲は1~999ではないです)
何に+1しましたか?
rand()%1000 + 1
だから、、、余りに+1ですか?

Re: 乱数について

Posted: 2014年1月02日(木) 14:04
by みけCAT
Sera さんが書きました:rand()%1000 + 1
だから、、、余りに+1ですか?
はい。
では、+1する前の余りの範囲はどうなりますか?
オフトピック
割られる数が負だと厄介ですが、C言語標準ライブラリのrandの戻り値は0以上のはずなので、ここでは無視します。

Re: 乱数について

Posted: 2014年1月02日(木) 14:08
by Sera
みけCAT さんが書きました:
Sera さんが書きました:rand()%1000 + 1
だから、、、余りに+1ですか?
はい。
では、+1する前の余りの範囲はどうなりますか?
+1しないので0からの範囲ではないでしょうか

Re: 乱数について

Posted: 2014年1月02日(木) 14:09
by みけCAT
Sera さんが書きました:+1しないので0からの範囲ではないでしょうか
Yes, 0以上999以下ですね。

Re: 乱数について

Posted: 2014年1月02日(木) 14:16
by 初級者
1〜1000の数がほしいけど、
rand()が返すのは0以上だしなぁ。

てなときは、こんな風に考える。

1〜1000を無理やり0始まりに変えてしまう。
そうすると、0〜999になる。
0〜999はrand()が返す値を1000で割った
あまりとして得られる。
後は、もともと1から始めたかったので、
1を足す。

結果:
1〜1000をrand()で得るには、
rand() % 1000 + 1

Re: 乱数について

Posted: 2014年1月02日(木) 17:26
by Sera
初級者 さんが書きました:1〜1000の数がほしいけど、
rand()が返すのは0以上だしなぁ。

てなときは、こんな風に考える。

1〜1000を無理やり0始まりに変えてしまう。
そうすると、0〜999になる。
0〜999はrand()が返す値を1000で割った
あまりとして得られる。
後は、もともと1から始めたかったので、
1を足す。

結果:
1〜1000をrand()で得るには、
rand() % 1000 + 1
では1~999は
rand() % 999 + 1
ということですね!