JP / EN

広告
2023/07/01

C言語で0から1の一様分布乱数を生成する

タグ:c++

C言語ではstdlibのrand関数を用いて整数乱数を作れる。 では小数まで含めた連続な乱数が欲しくなったらどうすればよいのだろうか。 結論としてはrand() / RAND_MAXで[0.0, 1.0]の一様分布が生成できる。


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

int main()
{
  srand(0);  // 再現性のためにseedを固定
  int i = 0;
  for(i = 0; i < 10; i++)
  {
    double rnd = (double)rand() / RAND_MAX;
    printf("%f\n", rnd);
  }
  return 0;
}
  


これを実行すると
    $ gcc rnd.c
    $ ./a.out
    0.840188
    0.394383
    0.783099
    0.798440
    0.911647
    0.197551
    0.335223
    0.768230
    0.277775
    0.553970
    
のように0から1までの値が大体均等に出ていることが確認できる。

細かいポイントであるが、このコードの場合値域は閉区間である。 つまりちょうど0や1が出現することは、低い確率であるがある。 数学的には連続一様分布から0や1が出現する確率は0である(というか どうんな数でもピッタリあった数が出現することは確率0である) が、プログラミング上は離散的に近似しているしている影響で、 0より大きい確率 1 / (RAND_MAX + 1) で0と1が出現する。 すなわち0や1がでたら困るようなコードを後段に入れてはいけない。

とはいえ0や1が出てはどうしても困る用途もあるだろう。その場合は 分母や分子に1を足すことで対処することができる。 rand() / RAND_MAXとする箇所で
  • rand() / RAND_MAX: [0, 1]
  • rand() / (RAND_MAX + 1): [0, 1)
  • (rand() + 1) / (RAND_MAX + 1): (0, 1]
  • (rand() + 1) / (RAND_MAX + 2): (0, 1)
のように端点を含めるかどうかが変化する。

おすすめ記事

C++ STLで0から1の実数値乱数を生成する

std::vector<bool>はテンプレート特殊化して別物になっている

C++ std::mapを値入りで初期化するのは初期化子リストでOK



このエントリーをはてなブックマークに追加

https://wonderhorn.net/