views:

496

answers:

2

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

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.

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?

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);
        }
    }
}
+10  A: 
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.

BFree
excellent, that's all I needed, thanks!
Edward Tanguay
Note : This is true for C# but also in many others languages (C, C++, Java, ...). You usually seed your RNG once, and reuse it as long as you need it. I can't remember how many times i saw people asking help on dev-related forums because they kept re-seeding their RNG.
Ksempac
I don't think this is threadsafe...
Rex M
Nope, it isn't, since the Next method isn't static and the MSDN doc on Random tells you only public static members are thread-safe.
Ksempac
+2  A: 

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:

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.

Jon Skeet
Nice solution if you need to be thread-safe. However, i would drop the helper method altogether in this case, since your helper method is reduced to one call on an existing item.
Ksempac
Oh absolutely. This is only an example of the approach :)
Jon Skeet
Is this really your 23,874th "TestRandom" program? :)
John Rasch