LCRANS(3M)

名前
lcrans - 線形合同法による乱数の生成

形式
cc [ flag ... ] file ... -lsunmath -lm [ library ... ]

    flag にはフラグ、 file にはファイル名、 library にはライブラリ名を指定します。

#include <sunmath.h>

#define LCRAN_MULTIPLIER 16807

#define LCRAN_MODULUS 2147483647L

int i_lcran_(void);

float r_lcran_(void);

double d_lcran_(void);

void i_lcrans_(int *x, int *n, int *l, int *u);

void u_lcrans_(unsigned *x, int *n, unsigned *l, unsigned *u);

void r_lcrans_(float *x, int *n, float *l, float *u);

void d_lcrans_(double *x, int *n, double *l, double *u);

void i_get_lcrans_(int *x);

void i_set_lcrans_(int *x);

void i_init_lcrans_(void);

機能説明

これらの関数は、整数型、単精度浮動小数点型、倍精度浮動小数点型の 一様疑似乱数を生成します。

線形合同法による乱数は、 次の式を用いた ..._lcran_() によって、一度に 1 つずつ生成されます。

	lcran_last = (LCRAN_MULTIPLIER * lcran_last) % LCRAN_MODULUS
i_lcran_() は lcran_last を返し、 r_lcran_() と d_lcran_() は lcran_last / LCRAN_MODULUS を返します。 これにより、乱数は次の範囲に含まれます。
型 | 下位境界 |  | 上位境界
 | 名前 | 値 | 名前 | 値
整数 | I_LCRAN_LB | 1 | I_LCRAN_UB | 2147483646
単精度 | R_LCRAN_LB | 4.656612873077392578E-10 | R_LCRAN_UB | 1
倍精度 | D_LCRAN_LB | 4.656612875245796923E-10 | D_LCRAN_UB | 0.9999999995343387127
lcran_last は 1 <= lcran_last <= 2147483646 を満たさなければなりませんが、 効率を高めるため、 ..._lcran_() ではその検査を行いません。

線形合同法による乱数は、 次の式を用いた ..._lcrans_() によって、一度に *n 個生成されます。
	lcran_last = (lcran_multiplier * lcran_last) % LCRAN_MODULUS ;
	return scale * (lcran_last + offset) ;
ここで、 scale と offset は *l と *u から算出されるため、 算出された乱数は [*l,*u] 内で一様に分布します。 したがって、 lcran_multiplier を変更すると、 ..._lcrans_() によって生成される乱数も変化しますが、 効率を高めるため、 ..._lcrans_() では LCRAN_MULTIPLIER を 16807 に固定して用いています。 固定の除数 LCRAN_MODULUS(2147483647L) は、 rand(3C) での欠陥を避けるため意図的に 2 の累乗になっていません。 関数に入るときには、 ..._lcrans_() は 1 <= lcran_last <= 2147483646 を満たすかどうかを調べ、必要に応じて lcran_last を変更します。

線形合同法による乱数発生アルゴリズムの状態 ( lcran_last と lcran_multiplier の 2 つの整数の配列) は、 i_get_lcrans_() で取得したり、 i_set_lcrans_() で設定することができます。 初期の状態に戻す場合は、 i_init_lcrans_() を使用します。

使用例

  間隔 [0,1] 内で 1000 個の倍精度乱数を生成する

    double x[1000] ; int i, n = 1000 ;
    double lb = D_LCRAN_LB, ub = D_LCRAN_UB ;
    for (i=0;i<n;i++) x[i] = d_lcran_();	/* または ... */
    d_lcrans_(x, &n, &lb, &ub) ;	/* 同じ出力がより効率的に得られる */

  間隔 [-10,+10] 内で 1000 個の整数乱数を生成する

    int x[1000] ; int n = 1000, lb = -10, ub = 10 ;

    i_lcrans_(x, &n, &lb, &ub) ;

関連項目
addrans(3M), drand48(3C), mwcrans(3M), rand(3C), random(3), shufrans(3M)

Knuth 著, 『準数値算法』( The Art of Computer Programming Volume II ), 渋谷政昭、中川圭介訳, サイエンス社.

Park and Miller, Random Number Generators: Good Ones are Hard to Find, Communications of the ACM, October 1988.

注意事項

lcrans(3M) と addrans(3M) のどちらを使用すれば処理効率が向上するかは、プログラムが 乱数生成関数を呼び出す回数によります。 通常の用途 (50 以上の呼び出しがある場合) では、 lcrans(3M)、 drand48(3C)、 rand(3C)、 random(3) に含まれる関数よりも、 addrans(3M)、 に含まれる関数を ( shufrans(3M) とともに) 使用する方が処理効率が向上します。 また、50 以下の呼び出しの場合は、 addrans(3M) よりも lcrans(3M) を使用することをお勧めします。 addrans(3M) は最初の呼び出しで、ADDRAN_SIZE に定義されている 55 のエレメント テーブルを初期化するため、オーバーヘッドが生じることから、この場合は lcrans(3M) のほうが処理効率は向上します。