【问题标题】:clarification regarding std::random_shuffle to shuffle the vector关于 std::random_shuffle 对向量进行洗牌的说明
【发布时间】:2021-08-14 09:17:28
【问题描述】:

我是 C++ 的初学者,想澄清一些事情。我有一个字符串向量,必须随机打乱它。

我正在尝试了解两者之间的区别

std::random_shuffle(vector.begin(), vector.end());
int myrandom(int i) {
    return std::rand() % i;
}


std::random_shuffle(cards_vector.begin(), cards_vector.end(), myrandom);

只要我在 main.c 开头调用以下函数,两者似乎都可以正常工作

srand(time(NULL)); 

我还在互联网上找到了另一个使用 std::default_random_engine 的解决方案

    auto rng = std::default_random_engine{};
    std::shuffle(cards_vector.begin(), cards_vector.end(), rng);

但是,即使在 main 中调用了随机种子,上述解决方案也总是返回相同的 shuffle。我不确定这是不是有意的。

如果有人可以向我澄清这一点,我将不胜感激。

【问题讨论】:

  • 请注意,std::random_shuffle 已在 C++17 标准中被删除,取而代之的是 std::shuffle
  • srand 与 C++ 随机功能无关。您需要为随机引擎播种。此处示例:en.cppreference.com/w/cpp/numeric/random
  • 另请注意,std::srand 用于旧的 C 函数 rand
  • std::shuffle()std::srand() 不相关。要播种std::default_random_engine,使用了不同的机制(通常是std::random_device)。
  • std::default_random_engine{std::random_device{}()}

标签: c++ vector std shuffle


【解决方案1】:

函数std::random_shuffle 有两个重载。简而言之,这意味着您可以使用不同数量的参数调用相同的函数。

  • 版本std::random_shuffle(vector.begin(), vector.end()); 调用由实现(编译器、操作系统、标准库...)定义的内部随机生成器。但是,它通常在内部使用std::rand

来自文档:

随机数生成器是实现定义的,但经常使用函数std::rand。

  • std::random_shuffle(cards_vector.begin(), cards_vector.end(), myrandom); 版本使用显式随机生成器(您定义的;即myrandom),它在内部调用std::rand

函数std::rand(来自C)生成一个pseudo-random number。这意味着一旦您设置了 seed,它将(每次)生成相同的数字序列。换句话说,序列是确定性的,取决于初始值(称为seed)。

要为std::rand 设置种子(初始值),您需要调用函数std::srand,它接受种子作为参数。

srand(time(NULL)); 语句是使用 "random"(实际上不是)种子初始化生成器的老常用技巧。确实,time(NULL) 函数返回的是当前时间,应该是每次调用都不同。

因此,每次您的程序启动时,您都会使用不同的数字设置种子,并且生成器 std::rand 每次都会产生不同的序列。


请注意std::random_shuffle 是一个旧的 C++ 函数,已被弃用。您确实应该使用它的替代品,即std::shuffle

但是,即使在 main 中调用了随机种子,上述解决方案也总是返回相同的 shuffle。我不确定这是不是有意的。

这背后的原理与上述相同。

在该示例中,您使用的是另一个(不同于std::rand)伪随机数生成器,即std::default_random_engine{}。此生成器默认使用默认种子初始化。

如果您想为不同的应用程序运行生成不同的结果,您需要使用种子初始化生成器,这意味着每次应用程序启动时都会有所不同。

更正确的代码是:

#include <algorithm>
#include <chrono>
#include <random>

// ...

auto rng = std::default_random_engine{std::chrono::system_clock::now().time_since_epoch().count()};

【讨论】:

    猜你喜欢
    • 2017-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多