在内部使用双打来生成随机整数

时间:2012-03-24 17:22:56

标签: c# random

我发布了一堆开源随机数生成器on my site,包括一个正态分布的随机数生成器。要生成10-20范围内的随机整数,我会写一些类似new NormalRandomGenerator(10, 20).Next()的内容。

有人发表了这条评论:

  

只是想知道是否有必要实现“int Next()”   术语“double NextDouble()”,作为双重转换的int(和   反之亦然)在某些硬件上可能会非常慢,包括最近的PC   硬件,虽然我不是特别关注最新的CPU   此刻。

我相信这条评论指的是当有人在我的某个课程内部调用Next(20)时,该调用转换为类似(int)someMersenneTwister.NextDouble() * 20的内容(我不记得是否使用了舍入)

我是这样实现的,因为MT既快速又高效(尽管它有很长的随机期)。根据我的理解,这是生成随机数的标准方法 - 调用Next(),返回[0 .. 1]范围内的double,然后乘以和类型转换为int。

我的设计方面有问题吗?是否有更好的方法(更高性能,更快)生成不使用双精度的整数随机数?

对不起,如果这听起来很模糊。我不确定这里是否有问题。

3 个答案:

答案 0 :(得分:3)

不是你的问题的答案(因为它目前的形式IMO没有意义)。但是查看代码我发现了许多错误和其他问题:

  1. 幼苗。随着时间的推移,你会在几毫秒内创建多个UniformRandomGenerator时导致种子冲突。您从System.Random
  2. 继承了该问题
  3. MersenneTwister.NextDouble质量低劣。 double有大约53个数字,你只填写了32个。差不多就像System.Random填充了31个。
  4. MersenneTwister.Next(int maxValue)现在在所需的时间间隔内延伸那个糟糕的双倍。如果间隔时间长,这可能会导致强烈的偏差。 System.Random有一个非常相似的问题。
  5. 计算Next(int minValue, int maxValue) 时,
  6. maxValue-minValue包含int溢出
  7. NormalRandomGenerator的构造函数将平均值计算为this.Mean = ((max - min) / 2) + min;。这是一个整数除法,因此如果max-min为奇数,则会导致偏差。奇怪的选择,因为this.Mean是双重的。
  8. 计算正态分布数字的代码看起来也很奇怪,但我无法帮助你,因为我不知道它应该做什么。

  9. 如果你想生成统一的随机整数,那就是我自己的问题的重复:Generating uniform random integers with a certain maximum,它专注于在不引入偏见的情况下有效地创建这些整数。我建议将我的答案与LukeH的答案结合起来。

答案 1 :(得分:0)

通过缩放范围[0..1]中的double来生成随机整数很好,只要生成的double足够均匀分布即可。但是,大多数伪随机数生成器(包括Mersenne Twister)本身生成(32位无符号)整数,因此如果我们不需要使往返加倍就会很好。

如果绑定N是2的幂,我们可以先生成一个32位随机整数X并取X mod N.这可以保证产生均匀分布的结果。但是如果N不是2的幂,则采用模数会在得到的分布中产生偏差(例如,有更多的32位无符号整数,其中X mod 7为0而不是6。)如果N很小,则检测到这样的偏见需要大量生成的数字,但理论上,分布不正确。

为了生成N范围内真正均匀分布的整数,对于不是2的幂的N,我们可以求助于采样算法:首先计算M使得它是2的最小幂,大于2 N(N = 13,M = 16,依此类推)。然后生成32位整数X,计算Y = X mod M.现在,如果Y = N,则丢弃它并产生另一个,直到Y <1。 N出现了。如果底层prng是好的,预期生成的数量的数量永远不会超过2(它取决于N),并且虽然不保证循环终止,但它将以极大的概率终止。在实际应用中,你需要在循环中放置一个限制计数器,然后回退到另一种方法,以防止发生偏差的生成器。

哪种方法最快?只有剖析才能说明问题。这取决于硬件,语言和代码质量。

在Knuth的TAOCP第2部分中可以找到更全面的讨论。

答案 2 :(得分:-1)

您可以使用'Random.Next Method':

http://msdn.microsoft.com/en-us/library/system.random.next.aspx

您将获得一个小于指定最大值的非负随机数,或者给出一个数字范围(最小值和最大值)

问候。