Search code examples
c#asp.netrandomrngcryptoserviceprovider

Random ThreadStatic Number within Ranges


How can I generate a random number from a range of numbers using a threadstatic seed?

I need to create random numbers within a range from multiple methods. The problem is the same old duplicates.

I found a MSDN blog that has a nice random generator, but I need a range between two values (typically 0 - 100).

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

public static class RandomGenNumber
    {
        private static RNGCryptoServiceProvider _global =
            new RNGCryptoServiceProvider();
        [ThreadStatic]
        private static Random _local;

        //this works
        public static int Next()
        {
            Random inst = _local;
            if (inst == null)
            {
                byte[] buffer = new byte[4];
                _global.GetBytes(buffer);
                _local = inst = new Random(
                    BitConverter.ToInt32(buffer, 0));
            }
            return inst.Next();
        }

        //this is what needs to be fixed
        public static int Next(int low, int high)
        {
            Random inst = _local;
            if (inst == null)
            {
                byte[] buffer = ????;

                _global.GetBytes(buffer);
                _local = inst = new Random(
                    BitConverter.ToInt32(buffer, 0));
            }
            return inst.Next();
        }
    } 

When I loop, I want to pass a range

//this is called on a loop and I want to avoid duplicates
     internal ExampleMember PopulateMember()
    {
        var member = new ExampleMember();

        member.gender = RandomGenNumber.Next(0, 100) < 42 ? "M" : "F";

        member.personalityTypeId = RandomGenNumber.Next(1, 45);

        member.age = RandomGenNumber.Next(20, 80);

        ...

I have read through dozens of posts here, but I could not find an example for ranges.

The byte way of generating the number seems nice and clean, but I can't get it working for a range. Should I pass Ints or double and multiply that? Or how can that buffer value be used in an overload for Next with a start and end range?


Solution

  • inst.Next() should be inst.Next(low, high). That's all. The seeding part does not need to be touched. Move it into a helper method (e.g. static Random GetThreadStaticRandom()).