(Translated by https://www.hiragana.jp/)
rand - Wikipedia

randは、つづしが擬似ぎじ乱数らんすうれつかえすような関数かんすうけられる名前なまえである。ランドランダムばれている。以下いかおも標準ひょうじゅんCライブラリのそれについて説明せつめいする。

概要がいよう

編集へんしゅう

以下いか基本きほんてきC99したがう。

C言語げんごヘッダーファイル stdlib.h で宣言せんげんされている、0以上いじょうかつ定数ていすうRAND_MAX以下いか数学すうがく使つかう「以上いじょう」「以下いか」でありりょうはしふくむ)の整数せいすうかえ関数かんすうである。標準ひょうじゅんではマルチスレッドについてれられておらず、POSIXではスレッドセーフに実装じっそうすることを要求ようきゅうしていない[1]

また、標準ひょうじゅんは、randが生成せいせいすべき乱数らんすうれつ品質ひんしつなど、乱数らんすうれつ乱数らんすうせいについてはなに言及げんきゅうしていない。当然とうぜん移植いしょくせい保証ほしょうされない。

初期しょき

編集へんしゅう

randのつづしがかえ乱数らんすうれつはsrandで初期しょきされる。srandをさずにrandを使つかった場合ばあいは、最初さいしょ引数ひきすうを1としてsrandをした場合ばあいおなじように動作どうさしなければならない。srandに相当そうとうするステートメントが、一部いちぶBASICでRANDOMIZEという名前なまえであったためランダマイズばれることもあるが、「乱数らんすうシード英語えいごばん (種子しゅし)」をあたえているだけで、なにかをランダムにしているわけではない。

実行じっこうごとにことなる乱数らんすうれつ生成せいせいするために、簡便かんべん手法しゅほうとしては時刻じこくなどが使つかわれる(後述こうじゅつのコードれい参照さんしょう)。暗号あんごうなどの応用おうようでは外部がいぶから予測よそく不可能ふかのう(ないし十分じゅうぶん困難こんなん)な方法ほうほう使つかわなければならない。ぎゃくに、シミュレーションを再現さいげんするなどの用途ようとでは、おな乱数らんすうシードを使用しようしておな乱数らんすうれつかえすようにする。

srandは乱数らんすうれつ種子しゅしあた初期しょきするものであるから、randを使用しようするたびにsrandをんだりするのは、あやまった用法ようほうである。

randの問題もんだいてん

編集へんしゅう

ふるいrandの実装じっそう生成せいせいする乱数らんすうれつは、問題もんだいがあるものがほとんどだったことが指摘してきされている[2]現代げんだい[いつ?]のライブラリでは問題もんだいがあるものはすくなくなっている[よう出典しゅってん]が、標準ひょうじゅん規格きかくしょしめされた実装じっそうれいがあまりいものではなかったことや、ふるいライブラリとおなじコードが使つかわれつづけているものもまだあることから、注意ちゅういようする。

前述ぜんじゅつ規格きかくしょしめされたれいをはじめ、randの実装じっそう線形せんけい合同ごうどうほう使つかわれていることがあるので、線形せんけい合同ごうどうほう欠点けってん注意ちゅういする必要ひつようがある。詳細しょうさい線形せんけい合同ごうどうほう#短所たんしょ参照さんしょうすること。

ライブラリによっては、標準ひょうじゅんがいだがよりこう品質ひんしつのrandom、rand48とう用意よういされていることがある。本格ほんかくてき用途ようとには、メルセンヌ・ツイスタひとしのより生成せいせいほう検討けんとうすべきである。

srandとシードの問題もんだいてん

編集へんしゅう

srand()にtime()とう現在げんざい時刻じこく (びょう単位たんい) をわたして初期しょきする方法ほうほうはよくかけるが、srandの実装じっそうによってはシードちかいとrandによって生成せいせいされる乱数らんすう相関そうかんせいたか出力しゅつりょくされるものがある。つまり下記かきれいのような実装じっそう方法ほうほうるプログラムを起動きどうしてからすうびょうおなじプログラムを起動きどうすると最初さいしょのうちはおな乱数らんすうれつ可能かのうせいたかい。これを回避かいひするためにはtimeでハッシュ関数かんすうとおしてからsrandにわたす、もしくはsrandをしたのちのrandはすうじゅうすうひゃくかいばすなどの対策たいさく必要ひつようである。またうまでもなくおなじロジックを採用さいようしたプログラムがどう一時いちじこく起動きどうされるなどしてsrandが同一どういつ初期しょきされた場合ばあい以降いこうまったおな乱数らんすうれつることになる。

形式けいしき

編集へんしゅう
#include <stdlib.h>
int rand(void);
void srand(unsigned);

コードれい

編集へんしゅう
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    int a;
    srand((unsigned int) time(0)); /* 現在げんざい時刻じこく取得しゅとくして乱数らんすうシードを初期しょきする。 */
    a = (int)((rand() / ((double) RAND_MAX + 1.0)) * 10); /* [0, 9] の範囲はんいのいずれかがかえる。 */
    printf("%d", a);
    return 0;
}

出力しゅつりょく結果けっかれい:

8

特定とくてい範囲はんい乱数らんすうもとめたいときにはa = rand() % 10とする方法ほうほうひろられているが、線形せんけい合同ごうどうほうなどの下位かいビットの乱数らんすうとしての品質ひんしつひく生成せいせいほうそなえるため、上記じょうきのコードれいのように上位じょういにあるビットを利用りようすることが推奨すいしょうされている[3]。とはいえりょうコードともrandのしつとは関係かんけいなく分布ぶんぷかたよりが発生はっせいする方法ほうほうであり注意ちゅうい必要ひつようである。

参考さんこう文献ぶんけん

編集へんしゅう

外部がいぶリンク

編集へんしゅう