【问题标题】:C++11 random numbersC++11 随机数
【发布时间】:2012-12-10 04:25:57
【问题描述】:

我需要生成随机数,但范围尽可能广(至少 64 位)。我不在乎分布是否完美,所以std::rand() 会起作用,但它只返回int。我知道 c++11 具有一些随机数生成能力,可以给出任何大小的数字,但使用起来非常复杂。有人可以发布一个简单示例,说明如何尽可能简单地使用它以尽可能简单的方式(如std::rand())获得所描述的功能(64 位或更多随机数)?

【问题讨论】:

    标签: c++ random c++11


    【解决方案1】:

    不是 C++11,但足够简单

    ((unsigned long long)rand() << 32) + rand()这里我们生成int64的两部分作为int32的

    正如JasonD 所指出的,它假定rand() 生成32 位整数。可以异或 rand() << xrand() << (2*x)rand() << (3*x) 等,其中x rand() 数字生成。应该也可以的。

    【讨论】:

    • 假设 rand() 实际上返回一个 32 位数字。如果不是 15 位,它可能只有 31 位。
    • @JasonD 是的,@RiaD 应该检查 RAND_MAX 来确定这一点。
    • 在 Microsoft cl 下,直到当前 19.x,RAND_MAX 为 0x7FFF,即 15 位。
    【解决方案2】:

    我们可以轻松地将随机数生成器引擎封装到类似 srand/rand 的方法中,如下所示:

    #include <random>
    #include <iostream>
    
    struct MT19937 {
    private:
        static std::mt19937_64 rng;
    public:
        // This is equivalent to srand().
        static void seed(uint64_t new_seed = std::mt19937_64::default_seed) {
            rng.seed(new_seed);
        }
    
        // This is equivalent to rand().
        static uint64_t get() {
            return rng();
        }
    };
    
    std::mt19937_64 MT19937::rng;
    
    
    int main() {
        MT19937::seed(/*put your seed here*/);
    
        for (int i = 0; i < 10; ++ i)
            std::cout << MT19937::get() << std::endl;
    }
    

    (与srandrand 一样,此实现不关心线程安全。)

    包装函数非常简单,您可以直接使用引擎。

    #include <random>
    #include <iostream>
    
    static std::mt19937_64 rng;
    
    int main() {
        rng.seed(/*put your seed here*/);
    
        for (int i = 0; i < 10; ++ i)
            std::cout << rng() << std::endl;
    }
    

    【讨论】:

    • 不幸的是,std::mt19937_64::default_seed 被标准化为 5489u,因此您的示例程序将始终产生相同的输出序列。
    • @JeffreyYasskin:是的。就像在srand() 中一样,您需要提供自己的种子才能获得不同的随机序列。
    【解决方案3】:

    这是为此目的使用 C++11 随机数生成的方法(调整自 http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution):

    #include <random>
    #include <iostream>
    int main()
    {
      /* Initialise. Do this once (not for every
         random number). */
      std::random_device rd;
      std::mt19937_64 gen(rd());
    
      /* This is where you define the number generator for unsigned long long: */
      std::uniform_int_distribution<unsigned long long> dis;
    
      /* A few random numbers: */    
      for (int n=0; n<10; ++n)
        std::cout << dis(gen) << ' ';
      std::cout << std::endl;
      return 0;
    }
    

    您可以使用cstdint 中的std::uintmax_t 来代替unsigned long long,以获得最大可能的整数范围(不使用实际的大整数库)。

    【讨论】:

    • 这对几乎所有用途都非常有用,但请注意,它只为种子提供sizeof(unsigned) 字节的熵。如果您需要更多,可以将std::seed_seq 传递给mt19937 的构造函数,以便传递任意数量的随机字节。
    猜你喜欢
    • 2014-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多