【问题标题】:Random number generation with C++ or Python使用 C++ 或 Python 生成随机数
【发布时间】:2012-03-20 09:10:15
【问题描述】:

听说计算结果对随机数生成器的选择非常敏感。

1 我想知道是否与编写自己的 Mersenne-Twister 或其他伪随机例程以获得良好的数字生成器有关。另外,我不明白为什么我不应该信任本机或库生成器作为 numpy 中的 random.uniform() 和 C++ 中的 rand() 。我知道我可以自己构建生成器,用于除均匀分布之外的分布(逆重新分区函数方法、极坐标方法)。但是使用一个内置的生成器进行统一采样是不是很邪恶?

2 默认的“时间”种子有什么问题?是否应该在代码示例中重新播种以及多久播种一次(以及为什么)?

3 也许你有一些关于这些主题的好链接!

--edit 更准确地说,我需要随机数用于多启动优化例程,以及均匀空间样本来初始化其他一些优化例程参数。我还需要蒙特卡洛方法(敏感性分析)的随机数。我希望精确度有助于确定问题的范围。

【问题讨论】:

  • 添加您使用这些数字的目的可能会很好。这将有助于决定他们需要有多“好”。

标签: c++ python random simulation probability


【解决方案1】:

在 C++ 中,<random> 库可能提供您所需的一切。它有 3 种不同的 PRNG 模板算法,包括 mersenne twister、3 个在这些算法之上使用的适配器、9 个具体的随机数生成器,以及对系统的非确定性随机数源的访问。

除此之外,它还有 20 个随机数分布,包括均匀分布、正态分布、伯努利分布、泊松分布和抽样分布。

这是 Stroustrup 的 C++11 FAQ 中的一个(稍作修改的)示例。

#include <iostream>
#include <random>
#include <string>
#include <vector>
#include <functional>

int main()
{
    auto rand = std::bind(
                    std::normal_distribution<>(15.0,4.0),
                    std::mt19937());

    std::vector<int> output(32);

    for (int i = 0; i<400; ++i)
        ++output[rand()];

    for (int i = 0; i<output.size(); ++i)
        std::cout << i << '\t' << std::string(output[i],'*') << '\n';
}

0
1
2       *
3       **
4       **
5       **
6       ***
7       ***
8       ******
9       ***************
10      **************************
11      ******************
12      ************************************************
13      ******************************************
14      ****************************************
15      *******************************
16      ***************************************
17      **************************************
18      *************************
19      *****************
20      ************
21      ************
22      *****
23      *******
24      ***
25      **
26
27      *
28
29
30
31

【讨论】:

    【解决方案2】:

    好吧,我不能谈论 C++,但 Python uses the Mersenne Twister。所以没有必要在 Python 中实现你自己的。此外,如果没有其他随机源,Python 仅使用系统时间作为种子;这是system-dependent 问题。另请参阅os.urandom 文档。

    不过,编写自己的代码很有趣。 MT Wikipedia page 上的伪代码清晰且易于实现。

    当然,通常的警告适用。这不是加密随机数生成器。 random.shuffle 不能生成较大列表的所有排列,依此类推。但是对于您指定的用途,Mersenne Twister 可能很好。

    【讨论】:

      【解决方案3】:

      Python 的random.uniform() 很好。其实it already uses Mersenne-Twsiter

      但是,您最好避免使用 C 和 C++ 的 rand(),因为它通常会产生错误的随机数(另请参阅 What common algorithms are used for C's rand()?)。更糟糕的是,在 Windows 上 RAND_MAX is only 0x7fff 所以你不能得到超过 32768 个不同的值。如果您可以使用 C++11,请检查新的 &lt;random&gt; 库,其中包含许多随机数生成器,包括 MT-19937。否则,您仍然可以使用Boost.Random


      随时间播种随机数生成器是可以的,只要 (1) 您不使用严重的密码学(无论如何您都不应该在密码学中使用 Mersenne-Twsiter),并且 (2) 可以保证不可能有两个种子的时间值相同,这会导致生成相同的序列。

      【讨论】:

        【解决方案4】:

        至少在 C++ 中,rand 有时质量很差,所以代码应该很少将它用于任何事情,除了儿童游戏中的掷骰子或洗牌。但是,在 C++ 11 中,添加了一组质量良好的随机数生成器类,因此您通常应该优先使用它们。

        基于time 的种子在某些情况下可以正常工作,但如果您想让其他人难以复制相同的数字系列(例如,如果您正在生成用于加密的随机数),则不能。通常,您只想在程序开始时播种一次,至少在单线程程序中是这样。使用多线程时,您经常需要为每个线程创建一个单独的种子,在这种情况下,您需要每个线程都以独特的方式开始,以防止在所有线程中生成相同的序列。

        【讨论】:

          猜你喜欢
          • 2014-09-21
          • 2013-11-09
          • 2012-05-20
          • 2021-08-14
          • 1970-01-01
          • 2012-03-18
          • 2015-07-19
          相关资源
          最近更新 更多