【问题标题】:Best method of getting a random number at an "index" from a seed?从种子的“索引”处获取随机数的最佳方法?
【发布时间】:2020-04-06 03:00:26
【问题描述】:

我想知道从索引中获取随机数的好方法。基本上,这是我想要的一个例子。

根据我对std::rand() / rand() 工作原理的了解,每次调用它时它都会给你一个随机数,每次你通过调用 std::srand 重置种子时,它都会给出相同的确切数字.但是 rand 的工作方式似乎非常全球化,这意味着每次调用它时,数字都会改变原始种子中的某个索引(我知道这并不是它在引擎盖下的工作方式)

// User manually provides a seed, not by std::time(nullptr)
get_random(3); // Return 1641
get_random(67); // returns 2782
get_random(5); // return 9832
get_random(67); // return 2782

请注意,如果我重复一个索引,我每次仍然从种子中得到相同的结果。我稍微考虑了一下,这是我最好的结果

int Class::get_random(int index) {
    std::srand(user_provided_seed); // reset the seed
    for (int i = 0; i < index; i++) {
        std::rand();
    }
    return std::rand();
}

上面的工作正常,基本上它只是期望一个随机数作为索引并使用这个数字,但我觉得上面的工作有点太多了,在我的程序中我实际上确实希望用户传入一个相当大的索引,大约 1000 秒,我觉得简单地调用 std::rand() 1000 次会浪费 CPU 时间。

有没有更好的方法来做到这一点?也许已经包含了一个功能,可以满足我的需要。另请注意,我不需要真正的随机数,而伪随机数非常适合我的情况。

【问题讨论】:

  • 小心!!! c++ 对 rand 的要求与 c 不同。使用 c,可以保证除了对 rand 的调用之外,其他任何东西都不会在伪随机数序列中前进。查看以下内容的“兼容性”部分:cplusplus.com/reference/cstdlib/rand
  • 如果你的类是only使用rand()的代码(即你程序中的所有其他代码都通过你的类并且不调用srand()或@987654329 @直接)您可以将所有生成的随机值存储在容器中。然后get_random(index) 可以检查该容器 - 如果index 有效,则从容器中返回元素,否则在循环中根据需要生成更多元素,可选择将它们存储在容器中,并返回所需的值。您还可以单独预先生成随机值以填充容器,并在以后检索它们
  • @enhzflep 注意到了,虽然我从来没有打算使用 C 版本
  • @NekoBit - 是的,我知道。正是出于这个原因,我才提到它。使用 c++ 时存在一种可能性,即您不会每次都返回相同的数字序列。 ;)

标签: c++ random


【解决方案1】:

有几种方法。首先正如@Peter 在评论中所说的存储随机值(如果没有其他人使用std::rand 或者您可以创建自己的std::random_engine,则可以使用)。

Class {
    ...
    std::vector<int> values;
    std::mersenne_twister_engine engine;
}
int Class::get_random(int index) {
    for (int i = values.size(); i <= index; i++) {
        values.push_back(engine());
    }
    return values[index];
}

或者您可以使用可以单独计算索引的伪随机函数。例如(在伪代码中,因为 afaik 在标准库中没有 sha):

int get_random(int index) {
    return (int)(sha256(str(seed) +  str(index));
}

【讨论】:

  • 这是一个很好的答案(不能批准没有足够的代表),因为我还不知道标准库中的随机类,我查看了 mersenne_twister_engine,实际上最终使用了 default_random_engine 因为我听说它可以更快一点(我打赌这并不重要,但我喜欢速度)并进行了优化。
  • 请记住,default_random_engine 是完全由实现定义的,尽管在这里应该不是问题。
【解决方案2】:

如果 rand() 是递归的,则可能没有其他方法。在这种情况下,随机序列中的每个下一个数字都是基于前一个数字计算的,因此每次都必须执行 rand()。我不确定 rand() 是否是递归的 - 您可能想在担心更好的解决方案之前检查这种可能性。

【讨论】:

    【解决方案3】:

    您在get_random 中的方法是您能做的最好的。

    C 标准要求rand 为给定种子输出相同的数字序列。但是,即使给出了种子,C 标准也没有具体说明该序列是什么。值得注意的是:

    • rand 使用未指定的算法生成伪随机数,该算法在 C 实现之间可能有所不同,including versions of the same standard library
    • rand 返回的值不大于 RAND_MAXRAND_MAX 在 C 实现之间可能有所不同。

    另见this question

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-25
      • 1970-01-01
      • 1970-01-01
      • 2018-09-22
      • 2010-09-13
      • 2014-07-31
      • 1970-01-01
      相关资源
      最近更新 更多