我在几个地方使用随机数,通常构建一个随机数生成器,每当我需要它。 目前我使用的马尔萨利亚Xorshift算法与系统当前时间播种了。 现在我对这个策略有些疑惑:如果我使用多台发电机,发电机的数量的独立性(随机)取决于种子(种子相同数量相同)。 由于我使用的时间(NS)作为种子和这段时间以来改变了这一工作,但我不知道是否会不会更好只使用一个单一发电机和如使其可作为单。 这会增加随机数的质量?
编辑:不幸的是C ++ 11是不是一种选择,但
编辑:更具体:我并不是说单身能增加随机数的质量,但只有一台发电机的使用和接种的事实。 否则,我必须确保不同发电机的种子是从另一个独立的(随机)。 极端的例子:我的种子两台发电机具有完全相同的号码 - >它们之间没有随机性
假设你有几个变量,每个都需要是随机的,独立于其他人,将与一些随机生成一个新的随机值,定期重新分配。 这种情况往往与蒙特卡罗分析,和游戏(虽然游戏的严谨性远小于它是蒙特卡洛)。 如果一个完美的随机数发生器存在,这将是罚款,使用它的单实例。 从发电机个伪随机数在n分配给变量x 1,下一个随机数到变量x 2,接下来要×3,依此类推,最后回来变量x 1上的下一个周期。 周围。 这里有一个问题:太多太多的PRNG不能使用这种方式时,独立测试失败的独立性检验,有的甚至无法对单个序列随机性测试。
我的方法是使用一个单一的PRNG发电机作为种子生成器的一组自包含的PRNG的N个实例的。 这些后面的PRNG的每个实例馈送单可变。 通过自包含的,我的意思是PRNG是一个对象,与国家在实例成员,而不是静态的成员或全局变量保持不变。 种子生成器甚至不需要是来自同一家庭的那些另一个N的PRNG。 它只是需要在多个线程试图同时使用种子生成器的情况下折返。 然而,在我的应用我觉得这是最好的线程开始,以保证可重复性之前成立的PRNG。 这是一个跑,一个执行。 蒙特卡洛技术通常需要数千处决的,也许更多,也许更多。 随着蒙特卡洛,可重复性是必不可少的。 因此,需要另一个随机种子发生器。 这一个种子用于生成变量的N个发电机的种子生成器。
重复性是很重要的,在蒙特卡洛世界最少。 假设在一些大规模故障运行长蒙特卡罗模拟结果数10234。 这将是很高兴看到在世界上发生了什么。 这可能是一个统计上的巧合,它可能是一个问题。 的问题是,在一个典型的MC设置,只有数据的最低限度记录,刚好够计算的统计信息。 要查看运行数10234所发生的事情,需要重复这种特殊情况,但现在一切都记录。
每当客户是相互关联的代码需要“独立”的随机数,你应该用你的随机数生成器类的同一个实例。
您可以使用随机数生成器类的不同的对象时,客户端不依赖于对方,这不要紧,他们是否收到同样的数字或没有。
需要注意的是用于测试和调试它是能够再次创建随机数的相同的序列是非常有用的。 因此,你应该不是“随机种子”太多。
我不认为它增加了随机性,但它减少了你需要创建一个对象,你要使用的随机数发生器每次内存。 如果发电机没有任何实例特定的设置,你可以做一个单身。
由于我使用的时间(NS)作为种子和这段时间以来改变了这一工作,但我不知道是否会不会更好只使用一个单一发电机和如使其可作为单。
这是一个很好的例子,当单身不是一个反模式。 您还可以使用某种控制反转 。
这会增加随机数的质量?
号的质量取决于生成随机数的算法。 你如何使用它是不相关的(假设它被正确使用)。
您的编辑:您可以创建某种保存您的RNG类的对象容器(或使用现有容器)。 事情是这样的:
std::vector< Rng > & RngSingleton()
{
static std::vector< Rng > allRngs( 2 );
return allRngs;
}
struct Rng
{
void SetSeed( const int seen );
int GenerateNumber() const;
//...
};
// ...
RngSingleton().at(0).SetSeed( 55 );
RngSingleton().at(1).SetSeed( 55 );
//...
const auto value1 = RngSingleton().at(0).GenerateNumber;
const auto value2 = RngSingleton().at(1).GenerateNumber;
工厂模式来救援。 客户端不应该担心它的依赖的实例化规则。 它允许交换创建方法。 而反过来,如果你决定使用不同的算法可以互换发电机类和客户端不需要重构。 http://www.oodesign.com/factory-pattern.html
- 编辑
新增伪(对不起,这不是C ++,它waaaaaay很久以前,因为我上次在它的工作)
interface PRNG{
function generateRandomNumber():Number;
}
interface Seeder{
function getSeed() : Number;
}
interface PRNGFactory{
function createPRNG():PRNG;
}
class MarsagliaPRNG implements PRNG{
constructor( seed : Number ){
//store seed
}
function generateRandomNumber() : Number{
//do your magic
}
}
class SingletonMarsagliaPRNGFactory implements PRNGFactory{
var seeder : Seeder;
static var prng : PRNG;
function createPRNG() : PRNG{
return prng ||= new MarsagliaPRNG( seeder.getSeed() );
}
}
class TimeSeeder implements Seeder{
function getSeed():Number{
return now();
}
}
//usage:
seeder : Seeder = new TimeSeeder();
prngFactory : PRNGFactory = new SingletonMarsagliaPRNGFactory();
clientA.prng = prngFactory.createPRNG();
clientB.prng = prngFactory.createPRNG();
//both clients got the same instance.
一大优势是现在,如果你想/需要改变任何的实现细节,什么事都没有在客户端更改。 你可以改变播种法,RNG算法和实例规则W / O不必触碰任何地方的任何客户端。