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

时间:2016-04-19 17:17:43

标签: c++ algorithm permutation

我试图对字母表的随机排列进行一些处理,但是每个排列产生相同的结果,尽管使用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;
}

2 个答案:

答案 0 :(得分:5)

问题

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

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

random_shuffle有两种形式:

  • 一个需要2个参数(开始/结束迭代器)

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

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

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

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

答案 1 :(得分:0)

  1. 为随机数生成器设定种子时,可以设置算法的起始点,该算法将提供一系列伪随机数。如果您始终使用相同的种子,则算法将始终具有相同的起点,并始终生成相同的数字序列。
  2. 每次调用srand时,都会重置种子并重置算法的起始点。
    1. 这里常见的错误是反复拨打srand。除非你有充分的理由不这样做(如果你这样做,你可能根本不应该使用rand和srand。Look to the <random> library)你应该在开始时拨打srand一次在使用该种子之后一次播种发生器的程序。
    2. srand也很贵。从性能角度来看,您不希望经常调用它。
  3. 所以:因为对create_permutation调用srand seed调用create_permutationcreate_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;
    }
    

    更现代的方法:

    COPY