【问题标题】:Why does srand create same numbers?为什么 srand 创建相同的数字?
【发布时间】:2020-02-23 02:54:22
【问题描述】:

我用 c 语言编写了一个创建随机矩阵的程序。 它创建一个像这样的字符串 (3,-6,2;5,2,-9;-8,20,7)。 “;”削减每一行和一个“,”每一列。现在我写了一个 rust 程序,可以进行矩阵加法或乘法运算。我用这个来称呼它:
./matrix ./test 3 3 "*" ./test 3 3

./matrix 调用我的 rust 程序,我给它 3 个参数。 (矩阵 1、运算符、矩阵 2) 它可以工作并且计算很好,但矩阵 1 和 2 总是相等的。我认为这是因为我根据时间使用 srand 并且因为我同时调用它,它会创建两次相同的结果。我还测试了 Matrixrandomizer,但没有将其包含在我的 rust 调用中,它总是会创建不同的矩阵。

在这里你可以看到我的 c 代码。

#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <string.h>

int main (int argc, char* argv[]) {
    // Zufallszahlengenerator initialisieren
    srand(time(NULL));

    if(argc < 3) {
        printf("Es fehlen Argumente");
    }   
    char matrix[100] = "";

    int r, c;
    r = atoi(argv[1]);
    c = atoi(argv[2]);

    if(r > 0 && c > 0) {
        for(int i = 0; i < r; i++) {
            for(int j = 0; j < c; j++){
                if(j == c - 1) {
                    int test = (1+rand()%9);
                    char buffer[50];
                    sprintf(buffer, "%d", test);
                    strcat(matrix, buffer);
                    }
                if(j < c - 1){  
                    int test = (1+rand()%9);
                    char buffer[50];
                    sprintf(buffer, "%d", test);
                    strcat(matrix, buffer);
                    strcat(matrix, ",");    
                }

            }
            if(i != r - 1) {
                strcat(matrix, ";");
            }   
        }       
    }
    printf("%s", matrix);
}

【问题讨论】:

  • 是的,就是这个原因。使用相同的值调用 srand() 将使 PRNG 处于相同的状态。如果您使用的是 POSIX 系统,请尝试 srand(time(NULL) + getpid()) /* remember to #include &lt;unistd.h&gt; */;(或者对于 Windows 可能是 srand(time(NULL) + GetCurrentProcessId()))。
  • 什么是./test 3 3? 3阶随机方阵?
  • 谢谢 :) 效果很好。 getpid 返回进程的 ID 对吗?因此,当您将其添加到 srand 的种子变量时,您在 srand() 中具有不同的值?
  • ./test 3 3 是我对 c 程序的调用,3 3 是矩阵的维度 :)

标签: c srand


【解决方案1】:

srand 想要一个种子作为参数。对于给定的种子,随机序列将是相等的。因此,如果您在很短的时间内以time(NULL) 作为参数调用srand 两次,那么您很有可能会给出相同的种子。

使用time(NULL) 作为种子是确保在正常情况下每次运行程序时都有不同输出的好方法。但在这种情况下,您需要添加更多内容。一种方法是添加一个额外的参数来作为盐(从散列中借用的术语),如下所示:

int salt = atoi(argv[3]);
srand(time(NULL) + salt);

然后确保使用不同的参数调用程序,如下所示:

./test 3 3 546

这里546是你选择的号码,两次通话应该不同。我建议让它们变得非常不同。如果它们仅相差一个,那么如果两个调用之间的时钟改变秒,您可能会遇到同样的问题。

另一种方法是使用getpid() 作为盐。如果您不愿意更改应该发送给程序的参数数量,这可能会更可取。

【讨论】:

  • @Stargateur 怎么了?这可能不是一个完美的解决方案,但它确实有效。
  • @stargateur 我编辑了错字atoi(argv[3]),显然“确保使用不同的参数调用函数”意味着添加第三个(种子)参数。
【解决方案2】:

srand 函数将seed 作为参数。对于相同的种子,伪随机数生成器将始终提供相同的输出序列。在任何离散系统(例如计算机)中都可以识别最小时间步长。因此,调用/matrix ./test 3 3 "*" ./test 3 3 可能发生在更小的时间步长上,这意味着它们同时发生并且time(NULL) 返回相同的时间、相同的种子、因此相同的随机序列和相同的矩阵。一个快速的解决方案是在 POSIX 系统中尝试 srand(time(NULL) + getpid())#include &lt;unistd.h&gt;,或者在 Windows 系统中尝试 srand(time(NULL) + GetCurrentProcessId())。一个更复杂的解决方案是提供 salt 您的初始种子,盐基本上是一个添加到种子中的值。但是,选择盐值完全是一个不同的话题。你可以找到它的指针here

【讨论】:

    猜你喜欢
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    • 2015-07-31
    • 1970-01-01
    • 2012-07-22
    • 1970-01-01
    • 2011-12-24
    • 2016-11-16
    相关资源
    最近更新 更多