【问题标题】:Program works only if I keep displaying something until solution is found仅当我一直显示某些内容直到找到解决方案时,程序才有效
【发布时间】:2016-05-31 20:36:11
【问题描述】:

我编写了一个程序来生成一个随机的数字数组。我知道,如果我创建一个for 结构来放置随机数,我可能会有重复的值。为此,我创建了一个单独的递归函数,它不断寻找重复项并将它们替换为其他值,直到只有不同的数字:

#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int n, m, k, row[100];
int verif(int v[100], int k)
{
    for(int i=0; i<k-1; i++)
        for(int j=i+1; j<k; j++)
            if(v[i]==v[j])
            {
                cout<<".";
                srand(time(NULL));
                v[i]=rand()%100+1;
                return verif(v, k);
            }
             return 1;
}
int main()
{
    k=10, n=10;
    srand(time(NULL));
    row[0]=rand()%n+1;
    srand(row[0]);
    for(int i=1; i<k; i++)
    {
        srand(row[i-1]);
        row[i]=rand()%n+1;
    }
    verif(row, k);
     for(int i=0; i<k; i++)
        cout<<row[i]<<" ";
    return 0;
}

我希望你能解释一下为什么verif 中的一个简单的cout 可以让我的程序运行,以及为什么没有它就无法运行。

【问题讨论】:

  • 你知道srand(time(NULL));是做什么的吗?
  • 请显示真实代码(包括这里缺少的任何全局变量等),这不会编译
  • 那你为什么会以错误的方式使用它呢?除非您正在使用古老的超慢机器
  • 如果没有您的minimal reproducible example,我们无法准确告诉您。但是,当您删除没有副作用的表达式时崩溃是未定义行为的常见指标。
  • 但是在这种情况下,您在调用依赖于秒的函数时会递归,因为 epoch 返回相同的结果 - 有效地递归调用函数一整秒或更长时间。使用cout 语句,递归会减慢,以至于您不会在那一秒内触发堆栈溢出。没有,你会的。 Look at the recursion depth with and without the sleep_for statement.

标签: c++


【解决方案1】:

这是长时间递归调用函数的结果,可能会在您的机器上触发堆栈溢出。

这个表达式

srand(time(NULL));

rand() 的随机数生成器播种为自纪元以来的当前秒数。自然,这个数字每秒只改变一次。重新播种rand 生成器将获得与上次相同的序列,因此下一行中rand()%100 + 1 的结果将保持不变,直到time(NULL) 的结果发生变化。

既然您已经确保 v[i]==v[j] 将是 true 直到自初始分配以来至少经过一秒钟,您再次递归调用此函数,(再一次(再一次...))直到您从您的“随机”数字生成过程中获取一个新值(至少已经过了一秒钟),或者您的堆栈空间不足。 (你崩溃了)

您可以通过使用一个比cout 语句保持执行时间更长的函数更清楚地看到这种情况的发生,例如

std::this_thread::sleep_for(std::chrono::milliseconds{500});

你可以在这里看到这样的效果on coliru

使用 sleep 函数(每次递归执行 500 毫秒),您可以获得大约 13 次递归。

没有它,您将获得 ~2846000 次递归。差别很大。

有更好的方法来获取一个范围内的一组非重复随机数,如this question 的答案所示。我自己偏爱 Darklighter 的回答。对于该答案,如果您想要 100 个元素中的 10 个元素,请生成包含 100 个元素的向量,随机播放,然后调整其大小以仅包含前 10 个元素。

【讨论】:

    【解决方案2】:

    cout 解决了这个问题,因为在控制台上打印一些东西需要时间。所有其余的代码大约需要 0 时间,因此每次你都这样做

      srand(time(NULL));
      v[i]=rand()%100+1;
    

    您将得到完全相同的数字,因为您总是使用相同的种子。然后我不能 100% 确定会发生什么,它可能是一个堆栈溢出,因为你一直在递归地调用函数,或者它可能是别的东西。其实这并不重要,因为真正的问题是你的种子。

    只有使用cout,你最终会得到一个不同的种子和一个不同的随机数。

    您应该只为 rng 播种一次。顺便说一句,如果你想要随机数,你应该使用来自 &lt;random&gt; 而不是 rand 的 rngs(实际上它应该被弃用,因为它的质量低下)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      • 2022-10-08
      • 1970-01-01
      • 1970-01-01
      • 2013-05-02
      • 1970-01-01
      相关资源
      最近更新 更多