【COBOL学習|実務向け】COBOL組込関数 FUNCTION RANDOM の「シード値省略」という罠と正しい乱数生成の実践

1. 導入: なぜ RANDOM 関数の挙動理解が重要なのか

業務システムにおいて、テストデータの作成や抽選ロジック、あるいはIDの採番などで「乱数」を扱うケースは意外と多く存在します。COBOLの組込関数 FUNCTION RANDOM は手軽ですが、その「シード値」の挙動を誤解していると、プログラムを再実行するたびに毎回同じ値が出力されるという「再現性」に悩まされることになります。本稿では、意図した通りに乱数を制御するための定石を解説します。

2. 基礎知識: シード値と擬似乱数

コンピュータで生成される乱数は、厳密には「擬似乱数」と呼ばれます。計算式に基づいて生成されるため、計算の起点となる「シード値(種)」が同じであれば、生成される数列も常に同じになります。
COBOLの FUNCTION RANDOM は、引数にシード値(0以上1未満の数値)を指定できますが、省略した場合には「前回生成時の状態」が引き継がれます。つまり、プログラムの初回起動時や、シード値を固定した状態では、何度実行しても同じ結果が返る仕様になっているのです。

3. 実装/解決策: 現在時刻をシードにする

完全にランダムな値を得るためには、実行するたびに変化する値をシードとして渡す必要があります。実務で最も一般的かつ有効な方法は、組込関数 FUNCTION CURRENT-DATE を利用して、現在の時刻(特に秒やミリ秒)をシード値に変換して渡すことです。これにより、プログラムを実行するたびに異なる乱数系列を開始させることが可能になります。

4. サンプルプログラム

以下は、システム日付・時刻を元にシードを設定し、0〜99の範囲で乱数を取得する実用的なサンプルです。

       IDENTIFICATION DIVISION.
       PROGRAM-ID. RANDOM-SAMPLE.
       WORKING-STORAGE SECTION.
       01  WS-SEED              PIC 9(8)V9(8).
       01  WS-CURRENT-DATE      PIC X(21).
       01  WS-SEC-PART          PIC 9(2).
       01  WS-RESULT            PIC 9(2).

       PROCEDURE DIVISION.
       MAIN-LOGIC.
  • 1. 現在の日時を取得 (YYYYMMDDHHMMSSss形式)
MOVE FUNCTION CURRENT-DATE TO WS-CURRENT-DATE.
  • 2. 秒部分を切り出してシード値を作成
MOVE WS-CURRENT-DATE(13:2) TO WS-SEC-PART.
  • 3. 秒を0.xxxxxxの形式に変換してシードとして設定
COMPUTE WS-SEED = WS-SEC-PART / 60.
  • 4. シード値を指定して乱数生成の初期化
COMPUTE WS-RESULT = FUNCTION RANDOM(WS-SEED).
  • 5. 乱数生成 (引数なしで呼ぶと、以降はシード値なしで推移する)
COMPUTE WS-RESULT = FUNCTION RANDOM 100. DISPLAY "生成された乱数: " WS-RESULT. GOBACK.

5. 応用・注意点: 現場での落とし穴

注意点1:初期化のタイミング
FUNCTION RANDOM のシード指定は、乱数系列の「初期化」を行うものです。ループ内で毎回シード値を指定し直すと、逆に乱数が偏ったり、同じ値が繰り返される原因になります。初期化はプログラムの開始時に一度だけ行い、以後は引数なしの FUNCTION RANDOM を呼び出すのが鉄則です。

注意点2:真の乱数ではない
金融系やセキュリティに関わる重要な抽選ロジックなど、高い予測不可能性が求められる場合には、標準の FUNCTION RANDOM では不十分な場合があります。その際は、OSの乱数生成機能(API)を呼び出すなど、より強固な手法を検討してください。あくまで「業務上の簡易的な振り分け」用途として適切に使い分けることが、ベテラン技術者の知恵といえます。

コメント

タイトルとURLをコピーしました