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

时间:2021-09-26 14:03:19

All I want is a pragmatic random number generator in C# so I can say e.g.

我想要的只是C#中一个实用的随机数生成器,所以我可以说例如

int dummyAge = MathHelpers.GetRandomNumber(20,70);

and have it seem quasi random, e.g. to generate dummy data.

它看起来像是随机的,例如生成虚拟数据。

Most stack overflow questions on this topic and on the web get into a philosophical discussions on true randomness which is not what I'm interested at the moment, e.g. I did one in PHP a long time ago which uses milliseconds/sleep which is fine for dummy data, I'm just trying to do this in C# quick.

关于这个主题和网络上的大多数堆栈溢出问题都会进入关于真正随机性的哲学讨论,这不是我目前感兴趣的,例如我很久以前在PHP中做过一次使用毫秒/睡眠,对于虚拟数据很好,我只想在C#中快速做到这一点。

Does anyone have a quick half-decent C# random number generator based on some time seed, etc. or, how could I change the following code so that it always doesn't generate the same 5 number in a row?

有没有人有一个快速的半合适的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);
        }
    }
}

3 个解决方案

#1


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

This way, you're not creating a new Random object every time, rather you're reusing the same one. When you recreate a new one quickly enough, they will yield the same results. If however, you reuse an existing one, you'll get randomness.

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

#2


BFree's answer is fine, but I think it's also worth mentioning a slightly different pattern - passing the Random instance into anything that needs it, rather than always using a single instance via a static variable. The downside of the latter approach is that Random isn't thread-safe. You either need some locking, or thread-local variables, or avoiding using multiple threads to start with. So I would adjust the original code in the question to:

BFree的答案很好,但我认为值得一提的是稍微不同的模式 - 将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);
        }
    }
}

It's just basic inversion of control, really. You might have one static RNG with locking round it, used to generate a new instance of Random in a thread-safe way when you need it (by randomly generating a seed and then using that to create the instance) then reusing the Random throughout a particular single-threaded set of operations.

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

#3


The problem (of 5 same numbers) is a timing problem, BFree's answer solves it. The Random class is self-seeding using the timer, your calls are so close together they use the same seed.

问题(5个相同的数字)是一个计时问题,BFree的答案解决了它。 Random类是使用计时器进行自播种,你的调用非常接近它们使用相同的种子。

#1


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

This way, you're not creating a new Random object every time, rather you're reusing the same one. When you recreate a new one quickly enough, they will yield the same results. If however, you reuse an existing one, you'll get randomness.

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

#2


BFree's answer is fine, but I think it's also worth mentioning a slightly different pattern - passing the Random instance into anything that needs it, rather than always using a single instance via a static variable. The downside of the latter approach is that Random isn't thread-safe. You either need some locking, or thread-local variables, or avoiding using multiple threads to start with. So I would adjust the original code in the question to:

BFree的答案很好,但我认为值得一提的是稍微不同的模式 - 将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);
        }
    }
}

It's just basic inversion of control, really. You might have one static RNG with locking round it, used to generate a new instance of Random in a thread-safe way when you need it (by randomly generating a seed and then using that to create the instance) then reusing the Random throughout a particular single-threaded set of operations.

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

#3


The problem (of 5 same numbers) is a timing problem, BFree's answer solves it. The Random class is self-seeding using the timer, your calls are so close together they use the same seed.

问题(5个相同的数字)是一个计时问题,BFree的答案解决了它。 Random类是使用计时器进行自播种,你的调用非常接近它们使用相同的种子。