random_shuffle 和 srand() 每次都给我相同的结果

Posted

技术标签:

【中文标题】random_shuffle 和 srand() 每次都给我相同的结果【英文标题】:random_shuffle and srand() give me the same result every time 【发布时间】:2016-04-19 17:17:42 【问题描述】:

我正在尝试对字母表的随机排列进行一些处理,但是尽管使用了 srand(myseed),但每个排列都会产生相同的结果 我已经包含了<algorithm> 标头。

string create_permutation(unsigned seed)

    srand(seed);
    string permutation = ALPHABET;
    random_shuffle(permutation.begin(), permutation.end());
    return permutation;


cout << create_permutation(2) << endl; // or 3, 4, 5 etc
// continuously returns 'XQACKHSLOJ,TRBZNGV.W FIUEYDMP

任何帮助将不胜感激。

编辑:最小、完整且可验证的示例

编辑 2: 调整到 mcve

#include <iostream>
#include <algorithm>   

using namespace std;

const string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
string create_permutation(unsigned seed)

    srand(seed);
    string permutation = ALPHABET;
    random_shuffle(permutation.begin(), permutation.end());
    return permutation;


int main()    
    cout << create_permutation(2) << endl; // or 3, 4, 5 etc
    // continuously returns 'XQACKHSLOJ,TRBZNGV.W FIUEYDMP
    return 0;

【问题讨论】:

我在发帖前确实浏览了这个问题,每个帖子都与我的帖子有任何相似之处,解决方案一直是使用我已经做过的 srand(seed)。跨度> 相关:停止使用random_shuffle,开始使用std::shuffle。前者已被弃用,最终将被丢弃。有关如何执行此操作的示例,请参阅链接中的最后一个示例。 你完整的例子不是很完整。你不能运行它。 如果您每次都使用相同的种子:请阅读文档。否则,cannot reproduce. @MatthewCliatt 嘿,元警察来了! 1) 我已经给了他指向 MCVE 帮助页面的链接,该页面告诉他“确保包含重现问题所需的所有信息”。 2)到目前为止,没有人投票结束这个,所以我不明白你的意思。 3) “这篇文章是可复制的!” 不是他提供的信息。 “使用他的平台和编译器,你会得到相同的结果。”如果不知道是哪个平台,我就无法做到。 【参考方案1】:

问题

随机播放不是随机的,因为 shuffle_random 每次调用随机数生成器时都使用相同的种子。

srand 不为random_shuffle 函数播种,它为randrandom_shuffle 播种通常 调用rand,但不必

random_shuffle有两种形式:

一个接受 2 个参数(开始/结束迭代器)

一个需要 3(开始/结束迭代器和随机生成器)。

您已经证明您知道如何使用第一种形式,但第一种形式的问题在于它在不同平台和不同编译器上的实现方式不同。它可能根本不使用rand(),这是srand种子的功能。

您应该使用 3 参数形式并将随机数生成器作为参数提供给函数。

您可以关注this detailed answer学习如何制作自己的随机数生成器,也可以将rand()提供给random_shuffle函数作为随机数生成器。

【讨论】:

【参考方案2】:
    当您播种随机数生成器时,您设置了一个算法的起点,该算法将提供一系列伪随机数。如果您始终使用相同的种子,算法将始终具有相同的起点并始终生成相同的数字序列。 每次调用srand 时,都会重置种子并重置算法的起点。
      这里的一个常见错误是重复调用srand。除非你有很好的理由不这样做(如果你这样做了,你可能根本不应该使用 rand 和 srand。Look to the &lt;random&gt; library)你应该在程序开始时调用一次 srand 来播种生成器一次又一次地使用那个种子。 srand 也很贵。从性能的角度来看,您不想经常调用它。

所以:由于每次调用 create_permutation 都会使用 seed 参数调用 srand 并且始终使用相同的种子值调用 create_permutation,因此对于随机数生成器的给定实现,create_permutation 将始终使用相同的随机数序列,从而生成相同的排列。

一个会产生不同排列的简单示例,只要程序运行的频率不超过每秒一次即可

#include <iostream>
#include <string>
#include <algorithm>
#include <ctime>

const std::string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
std::string create_permutation()

    std::string permutation = ALPHABET;
    std::random_shuffle(permutation.begin(), permutation.end());
    return permutation;


int main()
    srand(time(NULL)); // caveat: time's minimum resolution is 1 second.
                       // multiple executions of this program within 1
                       // second will get the same time and use the same seed.
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    return 0;

更现代的方法:

#include <random>
#include <algorithm>
#include <iostream>
#include<string>

const std::string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
std::random_device rd; // Warning: implementation of this is allowed to be stupid and 
                       // return the same value every time. Does not work in mingw 4.8
                       // Can't speak for 4.9 or greater
std::mt19937 randomizer(rd());


std::string create_permutation()

    std::string permutation = ALPHABET;
    std::shuffle(permutation.begin(), permutation.end(), randomizer);
    return permutation;



int main()

    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;

【讨论】:

你给出的第一个例子和作者的代码是一样的吧? 是的。奇怪的。不知道那里发生了什么。我猜粘贴缓冲区中有错误的东西。

以上是关于random_shuffle 和 srand() 每次都给我相同的结果的主要内容,如果未能解决你的问题,请参考以下文章

`rand()` 的用处 - 或者谁应该调用 `srand()`?

C++ STL应用与实现64: 如何使用shuffle和random_shuffle : 洗牌 (since C++11)

在 random_shuffle() 对象向量时出现很多错误?

random_shuffle

C++常用算法random_shuffle

使用Fisher-Yates 洗牌算法实现random_shuffle函数