C# Mersenne Twister 类






4.20/5 (10投票s)
2003年10月6日
4分钟阅读

105601

2930
一个伪随机数生成器。
引言
梅森旋转算法(Mersenne Twister,MT)是由Makoto Matsumoto和Takuji Nishimura[1][2]在1996-1997年间开发的一种伪随机数生成器(PRNG)。MT具有以下优点:
- 它在设计时考虑了各种现有生成器的缺陷。
- 比任何其他已实现的生成器具有更长的周期和更高的均匀分布阶数。(已证明其周期为2^19937-1,并保证了623维均匀分布特性。)
- 生成速度快。(尽管这取决于系统,据报道,在具有流水线和缓存的系统中,MT有时比标准的ANSI-C库更快。)
- 内存使用效率高。
功劳归于创作者
我提供了一个C#类(RandomMT
),它封装了创建者的工作。我不为他们的工作归功,我只是提供了一个面向对象(OO)版本的代码,您可以直接将其放入您的游戏或应用程序中。这项工作也源自CRandomMT
。CRandomMT
是一个C++包装器类,用于梅森旋转算法,原始Code Project文章可以在这里找到。在那篇文章中,我不仅介绍了一个用于这个出色的伪随机数生成器的包装器类,还讨论了MT算法的均匀分布及其速度提升。暂时我将参考那些文章,因为我无法访问最新版本的TrueTime
。
RandomMT
开发此C#版本类的灵感来自两方面。
- 我想学习C#,而学习新语言的最好方法就是转换您熟悉的、
- 我越来越多地考虑PC游戏开发的未来——特别是使用.NET语言。
这些思考促使我写了一篇文档,该文档在PC游戏开发方面既是假设性的,也是事实性的。有兴趣的人可以在这里找到那篇文章。
类描述
RandomMT::RandomMT()
这是默认的构造函数。
RandomMT::RandomMT(ULONG seed)
一个您可以提供种子值的构造函数。
RandomMT::~RandomMT()
析构函数。
RandomMT::SeedMT()
用于初始化或重新初始化随机数生成器。
ULONG RandomMT::RandomInt()
返回一个
unsigned long
类型的随机数。int RandomMT::RandomRange(int hi, int lo)
返回一个在指定范围内的
int
类型的随机数。int RandomMT::RollDice(int face, int number_of_dice)
返回指定骰子数量和面数的
int
类型的随机数。int RandomMT::D#(int die_count)
返回指定骰子数量(由#确定)的模拟投掷结果。这些只是`RollDice()`的包装。
int RandomMT::HeadsOrTails()
返回0或1,用于模拟抛硬币。
Example usage
namespace MersenneTwister
.
.
.
RandomMT random = new RandomMT();
int rand_3d6 = random.D6(3); // roll 3 six sided die
.
.
.
关于此实现的说明
我尽可能地严格遵循了我最初的C++实现。原始代码使用了指针运算,这在C#中是不可能实现的,并且保持代码为托管代码(根据MSDN)。如果有人知道更好的方法,请随时告知我。
更新:MT19937
我已将代码更新为使用算法的最新版本,MT19937。
类描述
以下是MT19937版本类的简要概述。
ulong genrand_int32()
生成[0, 0xffffffff]区间的随机数
long genrand_int31()
生成[0, 0x7FFFFFFF]区间的随机数
double genrand_real1()
生成[0,1]实数区间的随机数
double genrand_real2()
生成[0,1]实数区间的随机数
double genrand_real3()
生成[0,1]实数区间的随机数
double genrand_real53()
生成具有53位分辨率的[0,1]区间的随机数
int RandomRange(int lo, int hi)
返回[hi-lo+1]范围内的随机数
用法
namespace MersenneTwister
.
.
.
MT19937 random = new MT19937();
int rand_d6 = random.RandomRange(1,6); // roll 1 six sided die
.
.
.
关于演示应用程序
同样,演示应用程序相当简陋。该应用程序允许您投掷六个六面骰子,并记录每个数字出现的总次数——您可以投掷一次或一千次。
我使用了GDI+,正如我所说的,我正在学习C#以及.NET框架,因此我可能滥用或误用了GDI+的许多功能。
结论
追求完美的PRNG是一个持续的努力,计算机科学家和数学家都难以企及。梅森旋转算法通常被认为速度快、体积小且分布均匀。C#是一门令人兴奋的语言,我期待在不久的将来学习和使用它进行编程。
谢谢
感谢Makoto Matsumoto和Takuji Nishimura创建了该算法。
参考文献
- [1] "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number Generator", M. Matsumoto and T. Nishimura, ACM Transactions on Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3--30。
- [2] Mersenne Twister: A random number generator