在C#中生成准随机数的最简单方法是什么?

8
我想要的是一个实用的C#随机数生成器,这样我就可以轻松地使用,例如:
int dummyAge = MathHelpers.GetRandomNumber(20,70);

我希望生成的数据看起来类似随机,例如用于生成虚拟数据。

大多数关于此话题的stack overflow问题和网络上的讨论都涉及到关于真正的随机性的哲学探讨,而这不是我目前感兴趣的。很久以前我用PHP实现了一个使用毫秒/睡眠时间的程序,可以生成虚拟数据,我只是想快速地在C#中实现这个程序。

请问有没有基于某些时间种子等的快速、比较不错的C#随机数生成器,或者如何更改以下代码,以避免连续生成相同的5个数字?

using System;

namespace TestRandom23874
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("the random number is: {0}", MathHelpers.GetRandomNumber(1, 10));
            Console.WriteLine("the random number is: {0}", MathHelpers.GetRandomNumber(1, 10));
            Console.WriteLine("the random number is: {0}", MathHelpers.GetRandomNumber(1, 10));
            Console.WriteLine("the random number is: {0}", MathHelpers.GetRandomNumber(1, 10));
            Console.WriteLine("the random number is: {0}", MathHelpers.GetRandomNumber(1, 10));
            Console.ReadLine();
        }
    }

    public class MathHelpers
    {
        public static int GetRandomNumber(int min, int max)
        {
            Random random = new Random();
            return random.Next(min, max);
        }
    }
}

我认为你的意思是“伪随机”。准随机意味着其他事情。 - John D. Cook
我认为在这种情况下,“准”(“好像,仿佛,似乎,在某种意义或程度上,具有某种相似之处”)比“伪”(“不真实但具有外观”)更合适,因为对于普通用户来说,它们是真正的随机数,但对于数学家来说,它们只是“在某种程度上”是随机数。 - Edward Tanguay
2个回答

13
public class MathHelpers
    {
        private static Random random = new Random();
        public static int GetRandomNumber(int min, int max)
        {
            return random.Next(min, max);
        }
    }

通过这种方式,您不会每次都创建新的Random对象,而是重复使用同一个。当您快速重新创建一个新的Random对象时,它们将产生相同的结果。但是,如果您重复使用现有的对象,则会获得随机性。


1
注意:这适用于C#,但也适用于许多其他语言(C、C++、Java等)。通常情况下,您只需对RNG进行一次种子处理,然后在需要时重复使用即可。我记不清有多少次看到人们在开发相关论坛上寻求帮助,因为他们不断重新生成RNG的种子。 - Ksempac
不是,因为Next方法不是静态的,而MSDN关于Random的文档告诉你只有公共静态成员是线程安全的。 - Ksempac

2
Random实例传递到需要它的任何地方,而不是总是通过静态变量使用单个实例。 后者的缺点是Random不是线程安全的。 您需要一些锁定,或线程本地变量,或避免使用多个线程开始。 所以我会调整问题中的原始代码:

using System;

namespace TestRandom23874
{
    class Program
    {
        static void Main(string[] args)
        {
            Random rng = new Random();
            Console.WriteLine("the random number is: {0}", 
                MathHelpers.GetRandomNumber(rng, 1, 10));
            Console.WriteLine("the random number is: {0}", 
                MathHelpers.GetRandomNumber(rng, 1, 10));
            Console.WriteLine("the random number is: {0}", 
                MathHelpers.GetRandomNumber(rng, 1, 10));
            Console.WriteLine("the random number is: {0}", 
                MathHelpers.GetRandomNumber(rng, 1, 10));
            Console.WriteLine("the random number is: {0}", 
                MathHelpers.GetRandomNumber(rng, 1, 10));
        }
    }

    public class MathHelpers
    {
        public static int GetRandomNumber(Random random, int min, int max)
        {
            return random.Next(min, max);
        }
    }
}

实际上这只是基本的控制反转。你可能会有一个带锁的静态 RNG (随机数生成器),用于在需要时以线程安全的方式生成 Random 实例(通过随机生成种子然后使用它来创建实例),然后在特定的单线程操作中重复使用 Random


如果你需要线程安全的话,这是一个不错的解决方案。然而,在这种情况下,我会完全放弃 Helper 方法,因为你的 Helper 方法仅被用于对现有项目进行一次调用。 - Ksempac
哦,绝对没错。这只是一种方法的示例 :) - Jon Skeet
这真的是你的第23,874个“TestRandom”程序吗? :) - John Rasch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接