1

我的老师告诉我,在同一脚本的连续运行之间,在 awk 中获得随机不相关数字的唯一方法是保存用于归档的最后一个种子,然后在您开始另一次执行时再次读取它。

到目前为止,我正在尝试这个:

BEGIN {
    getline seed < "myseed.txt";
    srand(seed);
    print rand();
    print rand();
    print srand() > "myseed.txt";
}

但唯一的内容myseed.txt始终是 0,每次执行时我都会得到相同的随机数。

关于如何保存内部随机数生成器的状态,然后在同一脚本的不同执行之间准确地恢复生成随机数的任何想法?

4

3 回答 3

3

种子到底是什么似乎有些混乱。它是一个用作初始化随机数生成器的参数的值,仅此而已;它不包含随机数生成器的当前状态。如果你srand(N)用任何 N 调用,然后生成一些随机数,然后srand()再次调用(使用任何种子),返回值将是原始 N,无论你在此期间生成了多少随机数。

如果目标是有一个可重复的数字串,允许中断,那么您不仅需要保存种子,还需要保存自播种以来生成的随机数的数量,并在下一个开始时生成并丢弃这些随机数跑。这是一个可怕的 hack,你可能会更好地实现自己的 RNG,或者更有可能使用 awk 以外的东西。

如果目标是确保即使在一秒钟内运行两次也不生成相同的序列,那么您应该阅读Ed Morton 在他的评论中发布的链接上的讨论。

于 2013-05-11T14:47:32.433 回答
1

要么我误读了你的问题,要么你正在做与你想要达到的目标完全相反的事情。如果您从文件中读取种子,使用它,将相同的种子写回文件以供下次重新使用,您将始终拥有相同的种子,因此始终会产生相同的数字运行。

$ awk 'BEGIN{srand(1234);print rand()}' && sleep 1 && awk 'BEGIN{srand(1234);print rand()}'
0.240849
0.240849

如果您不提供种子,srand()它将使用自纪元以来的秒数:

$ awk 'BEGIN{srand();print rand()}' && sleep 1 && awk 'BEGIN{srand();print rand()}'
0.2776
0.668099

...因此它每秒只会产生一次新数字。您可以通过使用$RANDOM(如果您的外壳支持它;每次使用时更改)或自纪元以来的纳秒(如果您date支持它)作为种子来解决此问题,例如:

$ awk -v seed="$RANDOM" 'BEGIN{srand(seed);print rand()}' && awk -v seed="$RANDOM" 'BEGIN{srand(seed);print rand()}'
0.661197
0.325718

$ awk -v seed="$(date +%N)" 'BEGIN{srand(seed);print rand()}' && awk -v seed="$RANDOM" 'BEGIN{srand(seed);print rand()}'
0.588395
0.911353
于 2013-05-11T09:07:13.773 回答
1

srand(seed) 为 "seed" 取一个整数值

rand() 返回一个十进制数 >= 0 并且 < 1。

因此,保存 rand() 的输出以直接用作下一个种子将导致 srand() 始终使用零种子。看(记住对 srand() 的调用会返回使用的 PREVIOUS 种子):

$ awk -v s=0.1 'BEGIN{srand(s); print rand(); print srand()}'
0.566305
0
$ awk -v s=0.9 'BEGIN{srand(s); print rand(); print srand()}'
0.566305
0

因此,如果您想使用 rand() 的输出作为下一个种子,您需要将其乘以您希望种子小于的任何数字,例如 1,000,000:

$ awk 'BEGIN{
    if ( (getline s < "myseed.txt") > 0 ) {
        print "seed read from file =", s
        srand(1000000*s)
    }
    else {
        print "using default seed of seconds since epoch"
        srand()
    }
    r = rand()
    print r > "myseed.txt"

    print "seed actually used by srand() was:", srand()
    print "rand() =", r
}'
using default seed of seconds since epoch
seed actually used by srand() was: 1368282525
rand() = 0.331514

$ awk 'BEGIN{
    if ( (getline s < "myseed.txt") > 0 ) {
        print "seed read from file =", s
        srand(1000000*s)
    }
    else {
        print "using default seed of seconds since epoch"
        srand()
    }
    r = rand()
    print r > "myseed.txt"

    print "seed actually used by srand() was:", srand()
    print "rand() =", r
}'
seed read from file = 0.331514
seed actually used by srand() was: 331514
rand() = 0.677688

$ awk 'BEGIN{
    if ( (getline s < "myseed.txt") > 0 ) {
        print "seed read from file =", s
        srand(1000000*s)
    }
    else {
        print "using default seed of seconds since epoch"
        srand()
    }
    r = rand()
    print r > "myseed.txt"

    print "seed actually used by srand() was:", srand()
    print "rand() =", r
}'
seed read from file = 0.677688
seed actually used by srand() was: 677688
rand() = 0.363388

在第一次执行时,文件“myseed.txt”不存在。

于 2013-05-11T14:07:37.943 回答