随机函数总是返回相同的结果,尽管不同的种子
我试图创建一个随机数字发生器(从中随机数字稍后将被转换成[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
如果你对我的接近原来的问题(包括创建的字母数字字符的随机密码)的建议,我会很高兴听到它好。
编辑: 通过省略种子,这两个问题都立即修复。更多背后的结论可以在下面的评论中找到。如果有人解释为什么不同的种子仍然具有相同的价值,我很乐意听到它!
是的,你的种子需要是一个整数,所以你不能使用COMP-2。种子不需要是一个特定的大小,只是一个整数,你可能会使它非常大。
程序编译所花费的时间与任何事情无关。
您应该在第一次调用函数时指定SEED。之后,使用零。这将遵循“伪随机”序列。你不需要每次“种子”,所以不需要担心毫秒。
您应该始终输出您的种子,以便您可以在以后重新生成序列。使用时间会变得很棘手,因此改为使用包含种子的参数或单个记录文件。
从this post,似乎RANDOM
功能需要采取一个32位整数作为种子。但是,您声明WS-CURRENT-MILLISECONDS
为COMP-2
浮点数(在其他语言中为64位双精度浮点数)。
我想这会使它成为种子的无效参数,因此使用默认种子值0,或者只使用double的第一个或最后32位,所以您基本上得到part of the mantissa or significand对于你正在尝试的数字是一样的。
如果第一件事情发生,尝试使用0作为种子,我想你会得到相同的输出。无论如何,你可以尝试使用一些不同的整数进行播种,看看会发生什么。
我得到你要去的方向,它可能在某处,但种子'0'不会返回相同的结果。但是,我发现我根本不需要种子。我读过的资源总是建议第一个'RANDOM'调用应该有一个种子,但是它只是简单地离开种子就可以正常工作(并且按照预期的结果)。即使使用相同的时间戳,这也会导致不同的结果。感谢您与我思考! – 2013-03-04 18:54:50
'COMP-2'是一个64位的浮点数,'RANDOM'需要32位的种子,所以可能会发生其他一些事情。我更新了我的帖子。 – 2013-03-04 19:12:04
输入种子的原因是您可以测试您的代码。换句话说,你得到一个给定种子的预期序列。 – 2013-03-04 20:26:07
这里有一些源代码来产生随机数希望这有助于。
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.
如果没有数字可以重复,我认为它甚至不被视为伪随机数,更不用说随机数了。计划已经有一段时间了?当然'CALL'ing程序根本就不需要'LINKAGE SECTION'。 – 2015-02-21 00:55:53
它的意思是用于绘画,就好像你在哪里从帽子上绘制数字一样。你可以只有一个赢家。该计划是一个更大的程序的零件。对于额外的部件抱歉,他们应该在代码中留言。代码来自40岁的大型机程序。 – 2015-02-22 15:52:27
谢谢,清除它! – 2013-03-04 21:52:46