LoginSignup
21
19

More than 5 years have passed since last update.

Mac、iOSで、rand()関数の疑似乱数アルゴリズムがヘン!

Posted at

話の発端は、StackOverflowの、この質問にあった。

StackOverflow 日本語版 - c言語での乱数生成

質問に対する回答は、きわめて単純で、rand()関数を、取得したい乱数の個数分、呼んでやりましょうというもの。
いちおう、XcodeのCommand Line Toolで、サンプルコードを作って、それを実行してみて、ちゃんと意図したとおりの結果になることを確認する。が、ここで奇妙なことに気づく。
何度実行しても、初項が4になる。
試しに、こんなC言語のコードを書いて、Xcodeで実行してみる。

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

int main(int argc, const char * argv[]) {
    unsigned int i;
    unsigned int seed = (unsigned int)time(NULL);
    for (i = 0; i < 100; i++) {
        srand(seed + i);
        printf("%d, ", rand() % 7);
    }
    putchar('\n');

    return 0;
}

結果はこちら:

2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

2015年7月4日時点では4の繰り返しになりましたが、現時点(2015年7月6日)では2の繰り返しになります。値が変わったのは、乱数の種にtime()関数を使っているからでしょう。
7の剰余を使うと、同じ値の繰り返しになりますが、それ以外の剰余、たとえば3だと、「2, 1, 0, 2, 1, 0……」と循環数になります。
これはひとめで、まずいと思う。実践的には、srand()関数をなんども呼ぶことはないだろうが、毎回プログラムを実行すると、つねに初項がおなじというのは、きっと不都合な影響を出すに違いありません。たとえば、シューティングゲームのプログラムで、rand()関数を使って、標的を出現させたとしたら、ゲームスタートで、いつも同じ標的が、おなじ場所から現れる、ってことになる。
言い遅れましたが、実行環境は、MacBook Pro、OS X 10.10.4 Yosemite、Xcode 6.4、Clangのバージョンは、Apple LLVM version 6.1.0 (clang-602.0.53)。
同様のプログラムを、iOS 8.4のiPadで動かしても、おなじ結果になります。まあ、それはそうでしょうね。
Mac、iOS、Clang以外の環境だと、どうなるんだろうか?ざんねんながらApple製以外のコンピュータがないので、C言語をウェブ上で実行してくれるサイトで、実験してみました。

ideone
codepad

前出のコードを上の2箇所で実行したら、ぱっと見、規則性が認められない結果が得られました。
なにが悪いんでしょうか?Clang、それとも、Appleが用意したC言語の標準ライブラリ?
どなたか、C言語の疑似乱数アルゴリズムに詳しい方がいらっしゃいましたら、なんでもいいんで、情報を共有してもらえたらありがたいです。

21
19
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
19