在单独的函数中生成的随机数不是那么随机

时间:2016-03-09 00:24:23

标签: c# random

我有两个独立的函数,每个函数都生成一个来自相同范围的随机数(1-5)。不幸的是,大约90%的时间他们生成相同的数字。我知道在函数中你可以通过re-using the same Random object来解决这个问题,因为它发生的速度非常快,以至于系统时钟尚未真正改变并播种不同的“随机”值,但是当它出现时分散在多个函数中,解决此问题的最佳方法是什么?整个过程需要大约一整秒才能完成,这些功能不是背对背的,所以肯定(我认为)时钟已经在它们之间勾选,但那不是真的吗?

我对如何使用算法而不仅仅是Random生成数字有一些想法,但它们会更加繁重,我觉得有一个更简单的解决方案。

编辑:请投票的人解释一下吗?我很乐意根据你的建议改进这个问题。

3 个答案:

答案 0 :(得分:7)

走出这个洞:

  • 根据需要传递一个Random对象。

  • 使Random对象成为可见所有需要它的类的静态公共字段。请注意, Random不是线程安全的。如果你需要它是线程安全的,那么要么在它周围放置锁,要么使它成为本地线程并为每个线程分配一个。

  • 使用加密强度随机性。它没有这个问题。

  • 编写自己的伪随机数生成器,其行为优于内置伪随机数。

  • 完全使用其他随机源,例如从random.org下载blob或其他类似的东西。

现在删除的答案建议使用NewGuid作为随机源。不要这样做。 Guids保证是独一无二的;它们不能保证随机。特别是,guid生成器生成顺序唯一guid是完全合法的。 NewGuid实际上并没有这样做,这不是合同的一部分。使用guid表示框中的内容:框中显示“全局唯一标识符”,而不是“随机生成的标识符”。

评论者建议使用哈希码作为随机源。不要这样做。保证哈希码只是随机分布,只要它们需要在哈希表中给出良好的分布。特别是,我们无法保证散列函数的设计能够确保它们的低阶位分布良好。

仅使用由专家设计的随机性或伪随机性来产生随机性。生成随机性是一个困难的工程问题。仅仅因为您认为无法预测特定结果并不能使该结果成为随机数生成器的合适熵源。

答案 1 :(得分:2)

快速解决方案是在您的消费者之间共享随机种子。

一种方法是创建提供者:

public class RandomIntegerProvider 
{
     private static Random _globalRandomGenerator = new Random();

     public int Next()
     {
       //...
     }
}

编辑:

一篇非常有趣的帖子:

http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx

您可以使用不同的策略,甚至确保线程安全。

答案 2 :(得分:0)

OOP友好的方式是将它通过参数传递给函数,或通过构造函数参数传递给类,在那里它将存储为字段/属性。

这称为dependency injection - 如果您希望应用程序可测试且可扩展,那么您应该这样做!

一个例子:

void Caller()
{
    Random random = new Random();
    Foo(random);
    Bar(random);
}

void Foo(Random random)
{
    int randomNumber = random.Next();
}

void Bar(Random random)
{
    int randomNumber = random.Next();
}