Cobol 随机函数总是返回相同的结果,尽管种子不同
我正在尝试创建一个随机数生成器(一些随机数稍后将从中转换为[a-Z]字符)。我已经让随机生成器的主要部分工作,但我不断收到相同的随机结果Cobol 随机函数总是返回相同的结果,尽管种子不同,cobol,gnucobol,Cobol,Gnucobol,我正在尝试创建一个随机数生成器(一些随机数稍后将从中转换为[a-Z]字符)。我已经让随机生成器的主要部分工作,但我不断收到相同的随机结果0.6734141422 我面临的另一个问题是:有一半的时间我的程序编译得太快。由于我使用的是以毫秒为单位的当前日期,因此让我的程序快速编译将意味着给RANDOM函数提供相同的种子。我一直在考虑简单地添加一个计数器,在将每个种子应用于RANDOM之前将其除以计数器。这就足够了,还是有更优雅的解决方案 有人能给我解释一下,为什么我总是收到相同的随机结果,即使应用了
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
如果您对解决我的原始问题(创建由字母数字字符组成的随机密码)有什么建议,我也很高兴听到
编辑:
通过省略种子,这两个问题立即得到解决。这一结论背后的更多信息可以在下面的评论中找到。如果有人能解释为什么不同的种子仍然产生相同的价值,我会很高兴听到 From,似乎RANDOM
函数需要将32位整数作为种子。但是,您将WS-CURRENT-millides
声明为COMP-2
float(在其他语言中,是64位双精度)
我想这要么使它成为一个无效的seed参数,因此使用默认的seed值0,要么只使用double的前32位或后32位,因此您基本上得到的结果与您尝试的数字相同
如果第一件事发生了,尝试使用0作为种子,我想您将得到相同的输出。在任何情况下,您都可以尝试显式地使用一些不同的整数进行种子设定,看看会发生什么。From,似乎RANDOM
函数需要将32位整数作为种子。但是,您将WS-CURRENT-millides
声明为COMP-2
float(在其他语言中,是64位双精度)
我想这要么使它成为一个无效的seed参数,因此使用默认的seed值0,要么只使用double的前32位或后32位,因此您基本上得到的结果与您尝试的数字相同
如果第一件事发生了,尝试使用0作为种子,我想您将得到相同的输出。在任何情况下,您都可以尝试显式地使用一些不同的整数进行种子设定,看看会发生什么。是的,您的种子必须是整数,因此不能使用COMP-2。种子不需要是一个特定的大小,只需要一个整数,您可能会使它非常大 编译程序所花的时间与任何事情都无关 您应该在第一次调用函数时指定种子。之后,使用零。这将遵循“伪随机”序列。您不需要每次都“播种”,因此无需担心秒数
您应该始终输出种子,以便以后可以重新生成序列。这使得使用时间变得很棘手,因此取而代之的是使用一个参数或包含种子的单个记录文件 是的,种子必须是整数,因此不能使用COMP-2。种子不需要是一个特定的大小,只需要一个整数,您可能会使它非常大 编译程序所花的时间与任何事情都无关 您应该在第一次调用函数时指定种子。之后,使用零。这将遵循“伪随机”序列。您不需要每次都“播种”,因此无需担心秒数
您应该始终输出种子,以便以后可以重新生成序列。这使得使用时间变得很棘手,因此取而代之的是使用一个参数或包含种子的单个记录文件 这里有一些生成随机数的源代码,希望对您有所帮助
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.
识别部门。
程序ID.RANDGEN为“控制台应用程序2.RANDGEN”。
作者迈伦·丹森。
日期编辑。
* **************************************************************
*生成大于的随机数的子例程
*零且小于或等于所需的随机数,无
*复制品。(使用RANDGEN-AREA调用“RANDGEN”。)
*
*公式仅在2X2的每个数字中循环一次。
*创建从1到所需随机数的随机数
*然后传给你。
*
*使用RANDGEN的规则:
*
*随机数>零
*
*首次使用的访问次数必须=零。
*
*RANDOM-NUMBER=0,将为您构建一个种子
*当访问次数也为0时
*
*RANDOM-NUMBER NOT=零,将是RANDGEN的下一个种子
*你可以将自己的随机数种子传递给RANDGEN
*第一次使用RANDGEN时。
*
*通过在随机数字段中放置一个数字
*遵循以下简单规则:
*如果访问次数=零,则
*随机数>零。
*
*你可以选择种子,也可以让RANDGEN为你建立种子。
*
*如果你选择一粒种子,它将成为最后一粒种子
*RANDON-你收到的号码。
*如果SEED>RANDON-NUMBERS-NEEDED,则最后一个数字可以是任何数字。
*
*遵循以下简单规则:
*如果访问次数=零A