【发布时间】:2016-04-15 11:23:02
【问题描述】:
我的随机随机数生成器必须被调用多次,未指定:
WRITE(*,*) Random_Number_routine([optional seed])
我的随机数生成器有一个可选的整数参数,如果存在,它将使用它作为种子。如果不存在,它会调用 system_clock(i) 并使用 i 作为种子。到现在为止还挺好。但是,如果调用 Random_Number_routine 太快,超过每秒一次,则系统时钟没有机会改变 COUNT 参数,并返回相同的值。作为一个例子,考虑对https://gcc.gnu.org/onlinedocs/gfortran/SYSTEM_005fCLOCK.html中给出的例子的改编
PROGRAM test_system_clock
INTEGER :: count, count_rate, count_max
DO i = 1, 100
CALL SYSTEM_CLOCK(count, count_rate, count_max)
CALL srand(count)
WRITE(*,*) count, count_rate, count_max, rand()
END DO
END PROGRAM test_system_clock
test_system_clock 的输出是
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320589 1000 2147483647 0.640894175
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
5320590 1000 2147483647 0.640901804
4928363 1000 2147483647
count 参数只取两个值:5320589 和 5320590。如果将此参数用作 srand 中的种子,即
Call srand(count)
然后使用相同的种子并生成相同的随机数,可以在数据的最后一列中看到。解决这个问题的唯一方法是从单个种子生成 $N$ 随机变量,即
CALL SYSTEM_CLOCK(count, count_rate, count_max)
Call srand(count)
DO j = 1, n
res(j) = rand()
END DO
然而,这假设人们知道在调用例程之前需要多少随机变量 - 在这种情况下我不知道。
我唯一经历过的另一条路线是使用 Fortran 的 save 属性并保存以前使用的种子 - 如果它第一次执行例程,它使用 SYSTEM_CLOCK 来确定种子,持续运行通过以下方式更新种子某个整数。但是,这不会产生随机数,因为仅使用序列中的第一个数字。
其他软件如何解决这个问题?像 MATLAB 这样的程序是如何做到这一点的?以及如何调用随机数例程并保证新的随机数?
更新:回答 francescalus 评论:所以在显示的第一个代码块中,我已经调用了该例程 100 次,表中的最后一列给出了每次调用生成的随机数。随机数只有两个值:0.640894175 和 0.640901804。这似乎是因为只有两个种子值可用(如第一列所示)。我要确定的是,鉴于我在种子值更改时更快地调用例程,我如何获得随机数。即如果我调用例程 100 次,那么我期望 100 个随机值,而不是相同的两个值。会不会是 Fortran 的错误?
【问题讨论】:
-
我想我现在明白了。如果我使用的是 PRNG,我希望它能够更新适合下一个调用的状态,并按顺序给出下一个调用。也就是说,对于
call my_prng(deviate, state)之类的东西,我希望state是intent(inout)(或在内部存储)。作为用户,我不希望在初始化后每次调用都提供不同的种子(这更像是哈希函数而不是 PRNG)。
标签: matlab random fortran random-sample