0

乱数ジェネレーターを作成しようとしています (乱数は後で [AZ] 文字に変換されます)。ランダム ジェネレーターの主要部分は動作していますが、常に同じランダム結果を受け取り0.6734141422ます。

私が直面しているもう 1 つの問題は、プログラムのコンパイルが速すぎるということです。現在の日付をミリ秒単位で使用しているため、プログラムを高速にコンパイルすると、同じシードがRANDOM関数に与えられます。に適用する前に、各シードをカウンターで割るカウンターを単純に追加することを考えていましたRANDOM。これで十分でしょうか、それとももっと洗練されたソリューションがありますか?

異なるシード値が適用されているにもかかわらず、常に同じランダムな結果を受け取る理由を誰かに説明してもらえますか? プログラムを実行するたびに、この結果が得られます。

私が読んだ限り、OpenCobolに準拠しているPerCobolコンパイラを使用しています。

総括する:

  • 均等なシードを克服するにはどうすればよいですか?
  • 異なるシードで同じランダム結果を受け取るのはなぜですか?

    000100 IDENTIFICATION DIVISION.
    000200 PROGRAM-ID. RandomTest.
    
    ENVIRONMENT DIVISION.  
    
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 RANDOMRESULT PIC S9V9(10).
    
       01 WS-CURRENT-DATE-DATA.
        05 WS-CURRENT-DATE.
          10 WS-CURRENT-YEAR    PIC 9(04).
          10 WS-CURRENT-MONTH   PIC 9(02).
          10  WS-CURRENT-DAY    PIC 9(02).
        05  WS-CURRENT-TIME.
      10  WS-CURRENT-HOURS      PIC 9(02).
      10  WS-CURRENT-MINUTE     PIC 9(02).
      10  WS-CURRENT-SECOND     PIC 9(02).
      10  WS-CURRENT-MILLISECONDS   COMP-2.
    05  WS-DIFF-FROM-GMT        PIC S9(04).
    
       PROCEDURE DIVISION.
       PRGRM.
    
       PERFORM 4 TIMES
        MOVE FUNCTION CURRENT-DATE TO WS-CURRENT-DATE-DATA
        COMPUTE RANDOMRESULT = FUNCTION RANDOM (WS-CURRENT-MILLISECONDS)
        DISPLAY "Seed value: " WS-CURRENT-MILLISECONDS UPON SYSOUT
        DISPLAY "Random result: " RANDOMRESULT UPON SYSOUT
       END-PERFORM
    
       STOP RUN.
    

出力例:

Seed value: 8.222829361429599E-67
Random result: 0.6734141422
Seed value: 8.964670591567083E-67
Random result: 0.6734141422
Seed value: 9.335591206635825E-67
Random result: 0.6734141422
Seed value: 9.335591206635825E-67
Random result: 0.6734141422

私の元の問題 (英数字で構成されるランダムなパスワードの作成) にアプローチするための提案があれば、それも喜んで聞きます。

編集:シードを省略すると、両方の問題が一度に修正されます。この結論の背後にある詳細については、以下のコメントを参照してください。別のシードでも同じ値が得られる理由について誰かが説明してくれたら、それを聞いてうれしいです!

4

3 に答える 3

2

はい、シードは整数である必要があるため、COMP-2 は使用できません。シードは特定のサイズである必要はなく、整数である必要があり、おそらくかなり大きくすることができます。

プログラムのコンパイルにかかる時間は、何の関係もありません。

関数の最初の呼び出しで SEED を指定する必要があります。その後、ゼロを使用します。これは、「疑似ランダム」シーケンスに従います。毎回「シード」する必要はないので、ミリ秒を気にする必要はありません。

後でシーケンスを再現できるように、常にシードを出力する必要があります。時間を使用するのは難しいため、代わりにパラメーターまたはシードを含む単一レコード ファイルを使用します。

于 2013-03-04T21:37:32.413 に答える
1

この投稿から、RANDOM関数は 32 ビット整数をシードとして受け取る必要があるようです。ただし、 float (他の言語では 64 ビット double)WS-CURRENT-MILLISECONDSとして宣言しています。COMP-2

これにより、シードの無効な引数になり、デフォルトのシード値 0 が使用されるか、double の最初または最後の 32 ビットのみが使用されるため、基本的に仮数または仮数のいずれかの部分を取得していると思いますそれはあなたがしようとしている数字についても同じです。

最初のことが起こっている場合は、シードとして 0 を使用してみてください。同じ出力が得られると思います。いずれにせよ、いくつかの異なる整数を明示的にシードして、何が起こるかを確認できます。

于 2013-03-04T18:51:24.627 に答える
0

これが役立つことを願って、乱数を生成するソースコードを次に示します。

   IDENTIFICATION DIVISION.
   PROGRAM-ID.  RANDGEN as "ConsoleApplication2.RANDGEN".
   AUTHOR.  Myron D Denson.
   DATE-COMPILED.
  * ************************************************************** 
  *  SUBROUTINE TO GENERATE RANDOM NUMBERS THAT ARE GREATER THAN
  *    ZERO AND LESS OR EQUAL TO THE RANDOM NUMBERS NEEDED WITH NO
  *    DUPLICATIONS.  (CALL "RANDGEN" USING RANDGEN-AREA.)
  *     
  *    FORMULA CYCLES THROUGH EVERY NUMBER OF 2X2 ONLY ONCE. 
  *    RANDOM-NUMBERS FROM 1 TO RANDOM-NUMBERS-NEEDED ARE CREATED 
  *    AND PASSED BACK TO YOU.
  *
  *  RULES TO USE RANDGEN:
  *
  *    RANDOM-NUMBERS-NEEDED > ZERO 
  *     
  *    COUNT-OF-ACCESSES MUST = ZERO FIRST TIME USED.
  *         
  *    RANDOM-NUMBER = ZERO, WILL BUILD A SEED FOR YOU
  *    WHEN COUNT-OF-ACCESSES IS ALSO = 0 
  *     
  *    RANDOM-NUMBER NOT = ZERO, WILL BE NEXT SEED FOR RANDGEN
  *    YOU CAN PASS RANDGEN YOUR OWN RANDOM-NUMBER SEED
  *     THE FIRST TIME YOU USE RANDGEN.
  *     
  *    BY PLACING A NUMBER IN RANDOM-NUMBER FIELD
  *      THAT FOLLOWES THESE SIMPLE RULES:
  *        IF COUNT-OF-ACCESSES = ZERO AND 
  *        RANDOM-NUMBER > ZERO. 
  *    
  *    YOU CAN PICK THE SEED OR YOU CAN LET RANDGEN BUILD A SEED FOR YOU.
  *
  *       IF YOU PICK A SEED < RANDON-NUMBERS-NEEDED IT WILL BECOME THE LAST
  *          RANDON-NUMBER YOU RECEIVE BACK.
  *       IF SEED > RANDON-NUMBERS-NEEDED LAST NUMBER COULD BE ANYTHING.         
  *     
  *      THAT FOLLOWES THESE SIMPLE RULES:
  *        IF COUNT-OF-ACCESSES = ZERO AND 
  *        RANDOM-NUMBER = ZERO AND 
  *        RANDOM-NUMBER-NEEDED > ZERO  
  *         
  *     TO INSURING A DIFFERENT PATTERN OF RANDOM NUMBERS
  *        A LOW-RANGE AND HIGH-RANGE IS USED TO BUILD
  *        RANDOM NUMBERS.
  *        COMPUTE LOW-RANGE =
  *             ((SECONDS + HOURS + MINUTES + MS) * 1753).           
  *        A HIGH-RANGE = RANDOM-NUMBERS-NEEDED + LOW-RANGE
  *        AFTER RANDOM-NUMBER-BUILT IS CREATED 
  *        AND IS BETWEEN LOW AND HIGH RANGE
  *        RANDUM-NUMBER = RANDOM-NUMBER-BUILT - LOW-RANGE
  *               
  * **************************************************************         
   ENVIRONMENT DIVISION.
   INPUT-OUTPUT SECTION.
   FILE-CONTROL.
   DATA DIVISION.
   FILE SECTION.
   WORKING-STORAGE SECTION.
   01  WORK-AREA.
       05  X2-POWER                     PIC 9      VALUE 2. 
       05  2X2                          PIC 9(12)  VALUE 2.
       05  RANDOM-NUMBER-BUILT          PIC 9(12)  COMP.
       05  FIRST-PART                   PIC 9(12)  COMP.
       05  NOT-USED-NUMBER              PIC 9(12)  COMP.
       05  LOW-RANGE                    PIC 9(12)  VALUE ZERO.
       05  HIGH-RANGE                   PIC 9(12)  VALUE ZERO.
       05  YOU-PROVIDE-SEED             PIC X      VALUE SPACE.
       05  RUN-AGAIN                    PIC X      VALUE SPACE.
       05  PAUSE-FOR-A-SECOND           PIC X      VALUE SPACE.   
   01  SEED-TIME.
       05  HOURS                        PIC 99.
       05  MINUTES                      PIC 99.
       05  SECONDS                      PIC 99.
       05  MS                           PIC 99. 
  *
  * LINKAGE SECTION.
  *  Not used during testing  
   01  RANDGEN-AREA.
       05  COUNT-OF-ACCESSES            PIC 9(12) VALUE ZERO.
       05  RANDOM-NUMBERS-NEEDED        PIC 9(12) VALUE ZERO.
       05  RANDOM-NUMBER                PIC 9(12) VALUE ZERO.
       05  RANDOM-MSG                   PIC X(60) VALUE SPACE.
  *    
  * PROCEDURE DIVISION USING RANDGEN-AREA.
  * Not used during testing 
  *  
   PROCEDURE DIVISION.
   100-RANDGEN-EDIT-HOUSEKEEPING.
       MOVE SPACE TO RANDOM-MSG. 
       IF RANDOM-NUMBERS-NEEDED = ZERO
         DISPLAY 'RANDOM-NUMBERS-NEEDED ' NO ADVANCING
         ACCEPT RANDOM-NUMBERS-NEEDED.
       IF RANDOM-NUMBERS-NEEDED NOT NUMERIC 
         MOVE 'RANDOM-NUMBERS-NEEDED NOT NUMERIC' TO RANDOM-MSG
           GO TO 900-EXIT-RANDGEN.
       IF RANDOM-NUMBERS-NEEDED = ZERO
         MOVE 'RANDOM-NUMBERS-NEEDED = ZERO' TO RANDOM-MSG
           GO TO 900-EXIT-RANDGEN.
       IF COUNT-OF-ACCESSES NOT NUMERIC
         MOVE 'COUNT-OF-ACCESSES NOT NUMERIC' TO RANDOM-MSG
           GO TO 900-EXIT-RANDGEN.
       IF COUNT-OF-ACCESSES GREATER THAN RANDOM-NUMBERS-NEEDED
         MOVE 'COUNT-OF-ACCESSES > THAT RANDOM-NUMBERS-NEEDED' TO RANDOM-MSG
           GO TO 900-EXIT-RANDGEN.
       IF YOU-PROVIDE-SEED = SPACE AND RANDOM-NUMBER = ZERO
         DISPLAY 'DO YOU WANT TO PROVIDE SEED  Y OR N: '
           NO ADVANCING
           ACCEPT YOU-PROVIDE-SEED.  
       IF RANDOM-NUMBER = ZERO AND
          (YOU-PROVIDE-SEED = 'Y' OR 'y')
         DISPLAY 'ENTER SEED ' NO ADVANCING
         ACCEPT RANDOM-NUMBER. 
       IF RANDOM-NUMBER NOT NUMERIC
         MOVE 'RANDOM-NUMBER NOT NUMERIC' TO RANDOM-MSG
         GO TO 900-EXIT-RANDGEN.
   200-RANDGEN-DATA-HOUSEKEEPING.      
       MOVE FUNCTION CURRENT-DATE (9:8) TO SEED-TIME.
       IF COUNT-OF-ACCESSES = ZERO
         COMPUTE LOW-RANGE =
                ((SECONDS + HOURS + MINUTES + MS) * 1753).
       COMPUTE RANDOM-NUMBER-BUILT = RANDOM-NUMBER + LOW-RANGE.  
       COMPUTE HIGH-RANGE = RANDOM-NUMBERS-NEEDED + LOW-RANGE.
       MOVE X2-POWER TO 2X2.             
   300-SET-2X2-DIVISOR.
       IF 2X2 < (HIGH-RANGE + 1) 
          COMPUTE 2X2 = 2X2 * X2-POWER
           GO TO 300-SET-2X2-DIVISOR.    
  * *********************************************************         
  *  IF FIRST TIME THROUGH AND YOU WANT TO BUILD A SEED.    *
  * ********************************************************* 
       IF COUNT-OF-ACCESSES = ZERO AND RANDOM-NUMBER = ZERO
          COMPUTE RANDOM-NUMBER-BUILT =
                ((SECONDS + HOURS + MINUTES + MS) + HIGH-RANGE).
  * *********************************************     
  *    END OF BUILDING A SEED IF YOU WANTED TO  * 
  * ********************************************* 
  * *******************************************************
  * THE NEXT 4 LINE OF CODE ARE FOR TESTING  ON CONSOLE   *  
  * *******************************************************            
  *    IF COUNT-OF-ACCESSES = ZERO        
  *      DISPLAY 'SEED TIME ' SEED-TIME 
  *            ' RANDOM-NUMBER-BUILT ' RANDOM-NUMBER-BUILT 
  *            ' LOW-RANGE  ' LOW-RANGE.          
  * ***************************************************
  * THIS PROCESS IS WHERE THE RANDOM-NUMBER IS BUILT  *  
  * ***************************************************   
   400-RANDGEN-FORMULA.
       COMPUTE FIRST-PART = (5 * RANDOM-NUMBER-BUILT) + 7.
       DIVIDE FIRST-PART BY 2X2 GIVING NOT-USED-NUMBER 
         REMAINDER RANDOM-NUMBER-BUILT. 
       IF RANDOM-NUMBER-BUILT > LOW-RANGE AND
          RANDOM-NUMBER-BUILT < (HIGH-RANGE + 1)
         GO TO 600-RANDGEN-CLEANUP.
       GO TO 400-RANDGEN-FORMULA.
  * *********************************************     
  *    GOOD RANDOM NUMBER HAS BEEN BUILT        *               
  * *********************************************
   600-RANDGEN-CLEANUP.
       ADD 1 TO COUNT-OF-ACCESSES.
       COMPUTE RANDOM-NUMBER = 
            RANDOM-NUMBER-BUILT - LOW-RANGE. 
  * *******************************************************
  * THE NEXT 3 LINE OF CODE ARE FOR TESTING  ON CONSOLE   *  
  * *******************************************************
       DISPLAY RANDOM-NUMBER.
       IF COUNT-OF-ACCESSES < RANDOM-NUMBERS-NEEDED
        GO TO 100-RANDGEN-EDIT-HOUSEKEEPING.     
   900-EXIT-RANDGEN.
       IF RANDOM-MSG NOT = SPACE
        DISPLAY 'RANDOM-MSG: ' RANDOM-MSG.
        MOVE ZERO TO COUNT-OF-ACCESSES RANDOM-NUMBERS-NEEDED RANDOM-NUMBER. 
        MOVE SPACE TO YOU-PROVIDE-SEED RUN-AGAIN.
       DISPLAY 'RUN AGAIN Y OR N '
         NO ADVANCING.
       ACCEPT RUN-AGAIN.
       IF (RUN-AGAIN = 'Y' OR 'y')
         GO TO 100-RANDGEN-EDIT-HOUSEKEEPING.
       ACCEPT PAUSE-FOR-A-SECOND.
       GOBACK.
于 2015-02-20T23:06:47.830 に答える