C++ 为什么不直接使用随机设备呢?
我对c++11随机库有点困惑 我的理解:我们需要两个独立的概念:C++ 为什么不直接使用随机设备呢?,c++,c++11,random,C++,C++11,Random,我对c++11随机库有点困惑 我的理解:我们需要两个独立的概念: 随机引擎(可以是伪引擎(需要种子)也可以是实引擎) 分布:它使用特定分布将从引擎获得的数字映射到特定间隔 我不明白的是为什么不直接用这个: std::random_device rd; std::uniform_int_distribution<int> dist(1, 5); // get random numbers with: dist(rd); 这是一个很好的起点 我将综合几点: 它的成本不得而知。
- 随机引擎(可以是伪引擎(需要种子)也可以是实引擎)
- 分布:它使用特定分布将从引擎获得的数字映射到特定间隔
std::random_device rd;
std::uniform_int_distribution<int> dist(1, 5);
// get random numbers with:
dist(rd);
这是一个很好的起点
我将综合几点:
- 它的成本不得而知。 从这个“设备”读取一个数字的成本有多高?这是未指明的。例如,它可以在Linux系统上读取/dev/random,这可能会阻塞很长一段时间等待熵(熵本身由于各种原因存在问题)
std::random\u设备
通常比简单的伪随机算法慢。一般来说,这可能不是真的,但通常是真的。这是因为它可能涉及物理设备,或简单CPU以外的其他硬件
- 它实际上可能是确定性的。 C++11的std::random_设备不需要是非确定性的!实现可以并且确实将其实现为具有固定种子的简单RNG,因此它为程序的每次运行生成相同的输出
std::mt19937 e{std::random_device{}()};
std::mt19937 e{std::random_设备{}()}代码>
如果您只做一次可能没问题,但是如果您要做很多次,最好跟踪您的std::random_设备
,不要不必要地创建/销毁它
查看libc++源代码以实现std::random_device
,可能会有所帮助,这非常简单。它只是std::fopen(“/dev/uradom”)
上的一个薄包装。因此,每次创建一个std::random_设备时,您都会得到另一个文件系统句柄,并支付所有相关费用
据我所知,在windows上,std::random_device
表示对microsoft crypto API的一些调用,因此每次执行此操作时,您都将初始化并销毁一些加密库接口
这取决于您的应用程序,但出于一般目的,我不认为这种开销总是可以忽略不计的。有时是这样,然后这是伟大的
我想这与你的第一个问题有关:
相反,这是我在大多数示例/站点/文章中发现的:
std::random_device rd;
std::mt19937 e{rd()}; // or std::default_random_engine e{rd()};
std::uniform_int_distribution<int> dist{1, 5};
// get random numbers with:
dist(e);
std::随机设备rd;
std::mt19937 e{rd()};//或者std::default_random_引擎e{rd()};
std::均匀分布区{1,5};
至少我的想法是:
std::mt19937
是一种非常简单可靠的随机发生器。它是自包含的,将完全存在于您的流程中,而不会调用操作系统或其他任何东西。该实现是由标准强制执行的,至少在boost中,它在任何地方都使用相同的代码,这些代码源自原始的mt19937
论文。这段代码非常稳定,并且是跨平台的。您可以非常确信,在编译它的任何平台上,初始化它、从它进行查询等都将编译成类似的代码,并且您将获得类似的性能
- 相比之下,随机设备是相当不透明的。你不知道它到底是什么,它将要做什么,或者它的效率有多高。你甚至不知道它是否真的可以被获取——当你试图创建它时,它可能会抛出一个异常。你知道它不需要种子。您通常不需要从中提取大量数据,只需使用它生成种子即可。有时,它充当加密API的一个很好的接口,但实际上并不需要这样做,不幸的是,有时它不是。它可能对应于unix上的
/dev/random
,也可能对应于/dev/urandom/
。它可能对应于某些MSVC加密API(visual studio),也可能只是一个固定常量(mingw)。如果你交叉编译一些手机,谁知道它会做什么。(即使你得到了/dev/random
,你仍然有一个问题,那就是性能可能不一致——它可能看起来工作得很好,直到熵池耗尽,然后它像狗一样慢。)
我的想法是,std::random_device
应该像一个改进版的播种时间(NULL)
——这是一个低条,因为时间(NULL)是一个非常糟糕的种子。我通常在当天使用time(NULL)
生成种子的地方使用它。我真的不认为它在外面有用。 < Po> Okdoki,让我们澄清一些混淆吧!
<代码> STD::RealthMyPosivs/Cuff>是标准的C++,相当于
std::random_设备的实现具有确定性:
26.5.6等级随机_装置
2如果实现限制阻止生成非确定性随机数,则实现可采用随机数引擎
因此,std::random_device
可能永远不会与熵池交互,因此entropy
成员函数可能返回零:
26.5.6等级随机_装置
双熵()常数不例外
5返回:如果实现使用随机数eng
std::random_device rd;
std::mt19937 e{rd()}; // or std::default_random_engine e{rd()};
std::uniform_int_distribution<int> dist{1, 5};
std::mt19937 e{std::random_device{}()};
std::mt19937 e{std::random_device{}};