C++ 哪个C++;随机数引擎是否具有O(1)丢弃功能?
自C++11以来,有许多std随机数引擎。他们实现的成员函数之一是C++ 哪个C++;随机数引擎是否具有O(1)丢弃功能?,c++,c++11,random,complexity-theory,C++,C++11,Random,Complexity Theory,自C++11以来,有许多std随机数引擎。他们实现的成员函数之一是void discard(int long z),它跳过随机生成的z个数字。此函数的复杂性在www.cplusplus.com()上以O(z)表示 然而,在www.cppreference.com()上有一条注释说 对于某些引擎,“快速跳转”算法是已知的,它可以向前推进 不经计算,通过许多步骤(数以百万计)实现状态 中间状态转换 我如何知道哪些发动机的实际报废成本为O(1)?如果使用预计算的跳转点,O(1)将适用于存在的每个RNG
void discard(int long z)
,它跳过随机生成的z个数字。此函数的复杂性在www.cplusplus.com()上以O(z)表示
然而,在www.cppreference.com()上有一条注释说
对于某些引擎,“快速跳转”算法是已知的,它可以向前推进
不经计算,通过许多步骤(数以百万计)实现状态
中间状态转换
我如何知道哪些发动机的实际报废成本为O(1)?如果使用预计算的跳转点,O(1)将适用于存在的每个RNG。请记住,有些算法可能比O(z)更好,但不是O(1)-比如O(log2z) 如果我们谈论的是跳到任意点,事情就会变得有趣。例如,有一种已知的O(log2 z)提前跳转算法,它基于F.Brown的论文《任意步长随机数生成》,Trans。是Nucl。Soc。(1994年11月)。代码示例是 在C++11标准中有LCG RNG,不确定在特定实现中向前跳的速度有多快()
所有的RNG共享相同的属性,我认为根本不存在这样的东西。我的启发性结论是,
O(1)
-跳跃RNG基本上是一个散列,这意味着(例如,它可能根本不是“好的”RNG)
但是,即使您询问关于O(logz)
的问题,我也看不到在STL中实现了这一点。
在GCC的discard
函数中,我能够grep
的所有函数都是简单的循环
discard(unsigned long long __z)
{
for (; __z != 0ULL; --__z)
(*this)();
}
这不仅令人伤心,而且令人误解,因为只有在有有效方法的情况下,discard
才应该存在
唯一重要的是mersene
(如下),但它仍然是O(z)
Boost的Mersenne有一个skip函数,但它只在大于(默认值)10000000(!?)的skip时调用。这已经告诉我跳过的计算非常繁重(即使是O(logz)
)。
最后,信任显然对线性同余具有有效的丢弃,但仅在c=0
的情况下。(我不确定这是否会降低它作为RNG的实用性。)
事实是,std::linear\u conformential\u engine::discard(无符号长z)
绝对可以非常有效地实现。它主要相当于将a
乘以z
模m
(对于零和非零c
),这意味着大多数基本的软件实现都是在O(log(z%phi(m))
UIntType
乘法(phi(m))中执行的=m-1
表示素数和您指的是哪本手册?我试过MSDN(),因为我在Visual Studio中工作,但没有找到答案。这没有帮助,因为函数没有正确的文档记录,所以我一直在做自己的基准测试?使用STL似乎有点费力。您可以查看源代码,它可以在Visual Studio安装指南中免费获得谢谢,是的。from我能看到的所有丢弃(z)函数都是使用for循环绘制z随机数来实现的,所以O(z)。不确定我是否忽略了什么。我可以补充一点,RNG算法将强烈地决定这有多可能。想象一下一种算法,它逐步通过一个预先计算的“随机”表通过已知步长值进行编号。在这种情况下,表[(步长值*numSteps)%tableSize]
为O(1)。这是一个非常简单和有限的示例,但我在非常有限的系统上使用过类似的RNG方法,因此它在世界上占有一席之地。感谢您的回答。是的,我在寻找任意跳跃,而不是预先计算的跳跃。您链接到的PCG页面概述了原则上支持向前跳跃的引擎,优于O(z)。不过我真的很想知道O(1)。@alextack你让我想到了前跳的wrt O(1),我不确定这是否可能。基本上,应该有一个函数,其中有一个跳转值(比如说,64位)、状态值(XXX位)函数总是独立于跳转值进行相同数量的计算,以向前推进状态。可能不可能。您最好询问友好的mathexchange和/或交叉验证站点中是否存在此类RNG/函数。O(log2 z)对于me-30计算来说足够好,可以将RNG提高10亿。Blum-Blum-Shub也有这个特性,但在其他方面速度很慢。
discard(unsigned long long __z)
{
while (__z > state_size - _M_p)
{
__z -= state_size - _M_p;
_M_gen_rand();
}
_M_p += __z;
}
void discard(unsigned long long __z)
{
for (; __z != 0ULL; --__z)
(*this)(); //<-- Wait what? Are you kidding me?
}