2013-03-04 73 views
0

我试图创建一个随机数字发生器(从中随机数字稍后将被转换成[A-Z]字符)。我有随机发生器的主要部分工作,但我不断收到相同的随机结果0.6734141422随机函数总是返回相同的结果,尽管不同的种子

我正面临着另一个问题:我的程序编译速度过快一半。由于我以毫秒为单位使用当前日期,所以让我的程序快速编译将意味着RANDOM函数会使用相同的种子。我一直在考虑简单地添加一个计数器,它会将每个种子的计数器分配到RANDOM之前。这是否足够,还是有更多优雅的解决方案?

有人可以向我解释为什么我总是收到相同的随机结果,即使应用不同的种子值?每次执行程序时我都会得到这个结果。

我正在使用PerCobol编译器,就像我读过的那样,它与OpenCobol一致。

综上所述:

  • 我应该如何克服等于种子队?
  • 为什么我用不同的种子接收相同的随机结果?

    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 

如果你对我的接近原来的问题(包括创建的字母数字字符的随机密码)的建议,我会很高兴听到它好。

编辑: 通过省略种子,这两个问题都立即修复。更多背后的结论可以在下面的评论中找到。如果有人解释为什么不同的种子仍然具有相同的价值,我很乐意听到它!

回答

2

是的,你的种子需要是一个整数,所以你不能使用COMP-2。种子不需要是一个特定的大小,只是一个整数,你可能会使它非常大。

程序编译所花费的时间与任何事情无关。

您应该在第一次调用函数时指定SEED。之后,使用零。这将遵循“伪随机”序列。你不需要每次“种子”,所以不需要担心毫秒。

您应该始终输出您的种子,以便您可以在以后重新生成序列。使用时间会变得很棘手,因此改为使用包含种子的参数或单个记录文件。

+0

谢谢,清除它! – 2013-03-04 21:52:46

1

this post,似乎RANDOM功能需要采取一个32位整数作为种子。但是,您声明WS-CURRENT-MILLISECONDSCOMP-2浮点数(在其他语言中为64位双精度浮点数)。

我想这会使它成为种子的无效参数,因此使用默认种子值0,或者只使用double的第一个或最后32位,所以您基本上得到part of the mantissa or significand对于你正在尝试的数字是一样的。

如果第一件事情发生,尝试使用0作为种子,我想你会得到相同的输出。无论如何,你可以尝试使用一些不同的整数进行播种,看看会发生什么。

+0

我得到你要去的方向,它可能在某处,但种子'0'不会返回相同的结果。但是,我发现我根本不需要种子。我读过的资源总是建议第一个'RANDOM'调用应该有一个种子,但是它只是简单地离开种子就可以正常工作(并且按照预期的结果)。即使使用相同的时间戳,这也会导致不同的结果。感谢您与我思考! – 2013-03-04 18:54:50

+0

'COMP-2'是一个64位的浮点数,'RANDOM'需要32位的种子,所以可能会发生其他一些事情。我更新了我的帖子。 – 2013-03-04 19:12:04

+0

输入种子的原因是您可以测试您的代码。换句话说,你得到一个给定种子的预期序列。 – 2013-03-04 20:26:07

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. 
+0

如果没有数字可以重复,我认为它甚至不被视为伪随机数,更不用说随机数了。计划已经有一段时间了?当然'CALL'ing程序根本就不需要'LINKAGE SECTION'。 – 2015-02-21 00:55:53

+0

它的意思是用于绘画,就好像你在哪里从帽子上绘制数字一样。你可以只有一个赢家。该计划是一个更大的程序的零件。对于额外的部件抱歉,他们应该在代码中留言。代码来自40岁的大型机程序。 – 2015-02-22 15:52:27

相关问题