65.9K
CodeProject 正在变化。 阅读更多。
Home

C# Mersenne Twister 类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.20/5 (10投票s)

2003年10月6日

4分钟阅读

viewsIcon

105601

downloadIcon

2930

一个伪随机数生成器。

Sample Image - CsharpMersenneTwister.jpg

引言

梅森旋转算法(Mersenne Twister,MT)是由Makoto Matsumoto和Takuji Nishimura[1][2]在1996-1997年间开发的一种伪随机数生成器(PRNG)。MT具有以下优点:

  • 它在设计时考虑了各种现有生成器的缺陷。
  • 比任何其他已实现的生成器具有更长的周期和更高的均匀分布阶数。(已证明其周期为2^19937-1,并保证了623维均匀分布特性。)
  • 生成速度快。(尽管这取决于系统,据报道,在具有流水线和缓存的系统中,MT有时比标准的ANSI-C库更快。)
  • 内存使用效率高。

功劳归于创作者

我提供了一个C#类(RandomMT),它封装了创建者的工作。我不为他们的工作归功,我只是提供了一个面向对象(OO)版本的代码,您可以直接将其放入您的游戏或应用程序中。这项工作也源自CRandomMTCRandomMT是一个C++包装器类,用于梅森旋转算法,原始Code Project文章可以在这里找到。在那篇文章中,我不仅介绍了一个用于这个出色的伪随机数生成器的包装器类,还讨论了MT算法的均匀分布及其速度提升。暂时我将参考那些文章,因为我无法访问最新版本的TrueTime

RandomMT

开发此C#版本类的灵感来自两方面。

  1. 我想学习C#,而学习新语言的最好方法就是转换您熟悉的、
  2. 我越来越多地考虑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
© . All rights reserved.