C#の乱数生成はシード値を自分で設定しないといけないってのが新鮮だったぜ。

範囲指定(startからend-1まで)で乱数を取り出す関数。

private int get_random_number(int start, int end, int seed)
{
    var random = new System.Random(seed);
    return random.Next(start, end);
}

これを一回だけ実行するんならシンプルなんだが、seedが同じだと毎回おんなじ結果がでちまうので、なんべんも同時に実行する場合はseedを毎回変える必要がある。たとえば100回サイコロを振る処理はこう。

// seedの初期値を「プログラム開始からのミリ秒数」とする
int seed = Environment.TickCount;

// 出目の記録用カウンター
var arr = new int[] { 0, 0, 0, 0, 0, 0 };

// 1回振るたびにseedに1足していく
for (int i = 0; i < 100; i++)
{
    int dice = get_random_number(0, 6, seed + i);
    arr[dice]++;
}

// 結果を表記
Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}",
    arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]);

結果は以下。

16, 19, 16, 15, 18, 16

一様分布になってるので意図通りだ。オーケイ。

で、pyてょんちゃんで同じことするとこう。

import random
lis = [0,0,0,0,0,0]
for i in range(100):
    lis[random.randint(0,5)] += 1
print(lis)

震えるほどシンプルだ。randintの出目は第二引数を含むってとこがポイントかな。で結果は。

[16, 24, 14, 12, 16, 18]

って、アレ? なんだかC#よりもバラつきが大きい気がする。最小値と最大値で二倍の差がある。試しに10000回実行して、出目と割合を見てみた。

# 出目
[1653, 1682, 1618, 1697, 1660, 1690]
# 割合
[0.1653, 0.1682, 0.1618, 0.1697, 0.166, 0.169]

あ、これなら一様といっていいかも。C#は少数の実行でもきちんとバラけて、Pythonはそうでもない、と。言語によって乱数生成のアルゴリズムが違うってことを目の当たりにできたぜ。