如何在不使用时间作为种子的情况下在C ++中生成随机数

时间:2017-01-26 14:37:11

标签: c++ c++11 random

我的程序应该生成固定最大值为9999的随机数。这些数字用于创建对象。现在问题是当使用时间作为种子时,如果我一个接一个地创建两个对象,则两个对象都将使用相同的数字创建(因为时间没有在过程中发生变化)。

如何更有效地完成这项工作,以便每次运行程序时都可以生成不同的随机数?

3 个答案:

答案 0 :(得分:8)

关键是 - 只创建一个随机对象(或其状态),然后重复使用它以获取下一个值。这种方法通常用于其他语言,例如Java,C#,Python。

对于较旧的C风格示例,请参阅rand,这是您感兴趣的位

var ci = event.relatedTarget.getAttribute("c_index");
Meta.elements[ci] = {CurrParent: "workspace"};

C++11相同的想法,例如uniform distribution

//initialize random seed ONCE
srand (time(NULL));

// call MANY TIMES for next value
rand();
rand();
rand();

答案 1 :(得分:1)

用于生成随机数的简单C ++类。头文件。

#include <stdio.h>
#include <tchar.h>

#include <random>  
#include <iostream>
#include <algorithm>
#include <vector> 

namespace Random
{
    /// <summary>
    /// Secure pseudo random number generator.
    /// </summary>
    class RandomGenerator
    {
    public:
        /// <summary>
        /// Random number generator.
        /// </summary>
        RandomGenerator();

        /// <summary>
        /// Random number generator destructor.
        /// </summary>
        ~RandomGenerator();

        /// <summary>
        /// Get the randomly ordered numbers between the lower bound and upper bound inclusive. Each random value only occurs once.
        /// </summary>
        /// <param name="lowerBound">The smallest random value to generate.</param>
        /// <param name="upperBound">The largest random value to generate.</param>
        /// <returns>The list of randomly ordered values.</returns>
        /// <exception cref="std::invalid_argument">Invalid parameters.</exception>
        std::vector<int> GetRandomList(int lowerBound = 1, int upperBound = 52);

        /// <summary>
        /// Get the random number between the lower bound and upper bound inclusive.
        /// </summary>
        /// <param name="lowerBound">The smallest random value to generate.</param>
        /// <param name="upperBound">The largest random value to generate.</param>
        /// <returns>A random value.</returns>
        /// <exception cref="std::invalid_argument">Invalid parameters.</exception>
        int Generate(int lowerBound, int upperBound);

    private:
        bool _disposed;
    };
}

代码文件。

#include "RandomGenerator.h"

using namespace Random;

/// <summary>
/// Random number generator.
/// </summary>
RandomGenerator::RandomGenerator() : _disposed(false)
{
}

/// <summary>
/// Random number generator destructor.
/// </summary>
RandomGenerator::~RandomGenerator()
{
    // If not disposed.
    if (!_disposed)
    {
         // Indicate that dispose has been called.
         _disposed = true;
    }
}

/// <summary>
/// Get the randomly ordered numbers between the lower bound and upper bound inclusive. Each random value only occurs once.
/// </summary>
/// <param name="lowerBound">The smallest random value to generate.</param>
/// <param name="upperBound">The largest random value to generate.</param>
/// <returns>The list of randomly ordered values.</returns>
/// <exception cref="std::invalid_argument">Invalid parameters.</exception>
std::vector<int> RandomGenerator::GetRandomList(int lowerBound, int upperBound)
{
    // Validate input.
    if (lowerBound > upperBound)
          throw std::invalid_argument("The parameters are invalid, the lower bound can not be larger then the upper bound.");

    std::vector<int> numbers;
    int arraySize = upperBound - lowerBound + 1;

    // Allocate the total number of values.
    numbers.resize(arraySize);

    // For each value in the bounds.
    for (int i = lowerBound; i <= upperBound; i++)
    {
         // Assign the numbers.
         numbers[i - lowerBound] = i;
    }

    // Non-deterministic generator
    // to seed mersenne twister.
    // Random values on each execution.
    std::random_device rd;
    std::mt19937 engine(rd());

    // Shuffle the numbers between the lower and upper bounds.
    std::shuffle(numbers.begin(), numbers.end(), engine);

    // Return the randomly ordered numbers.
    return numbers;
}

/// <summary>
/// Get the random number between the lower bound and upper bound inclusive.
/// </summary>
/// <param name="lowerBound">The smallest random value to generate.</param>
/// <param name="upperBound">The largest random value to generate.</param>
/// <returns>A random value.</returns>
/// <exception cref="std::invalid_argument">Invalid parameters.</exception>
int RandomGenerator::Generate(int lowerBound, int upperBound)
{
    // Validate input.
    if (lowerBound > upperBound)
         throw std::invalid_argument("The parameters are invalid, the lower bound can not be larger then the upper bound.");

    int randomValue;

    // Non-deterministic generator
    // to seed mersenne twister.
    // Random values on each execution.
    std::random_device rd;
    std::mt19937 engine(rd());

    // Use the uniform distribution to generate
    // a value between lower and upper bound inclusive.
    std::uniform_int_distribution<> dist(lowerBound, upperBound);

    // Generate the random value.
    randomValue = dist(engine);

    // Return the random value.
    return randomValue;
}

答案 2 :(得分:0)

为了更好地理解,我将向您展示线性同余生成器的工作原理。

对于这种类型的生成器,数学非常简单:

xi+1=(A*xi+B) mod N

其中A,B和N是常数。

代码可以是:

static unsigned int x;  //the seed (time in your case)

unsigned int myRand(){
    x=A*x+B;    //We do not need modulo because it is implicit. For 32b integer the modulo will be 2^32.
    return x;
}

因此,当您设置x =时间时,如果时间没有改变,您只需重置发生器。

所以问题的解决方案可能是:

#include <iostream>
#include <time.h>
#include <stdlib.h>

int main() {
    srand(time(NULL));
    for (unsigned int i=0; i<10;i++){
        std::cout << random()%(9999+1)<<std::endl;
    }
}

或尝试这种不同的方法:

#include <iostream>
#include <random>

int main() {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> distribution(0,9999);

    for (unsigned int i=0; i<10;i++){
            std::cout << distribution(gen)<<std::endl;
    }
}

有关random_device的更多信息:http://www.cplusplus.com/reference/random/random_device/