Working with random numbers and generics

avirag 0 Tallied Votes 224 Views Share

This is a snippet that takes a min value, max value and how many
random numbers from the user then, after it checks to make sure it's
not already in the list, adds the new random number to a List..

I hope it helps you..... :)

/// <summary>
/// method for generating a certain amount of random numbers
/// The user provides how many random numbers to generate, and the
/// minimum and maximum values the randon numbers can be
/// </summary>
/// <param name="min">minimum value</param>
/// <param name="max">maximum value</param>
/// <param name="howMany">how many random numbers the user wants</param>
/// <returns></returns>
private static List<int> GenerateRandomNumbers(int minValue, int maxValue, int howMany)
{
    //create a generic list of integers
    List<int> numberList = new List<int>();

    //create an instance of the random class
    Random rand = new Random();

    //a loop for how many random numbers the user wants
    for (int i = 0; i < howMany; i++)
    {
        int value = rand.Next(minValue, maxValue);
        //check and make sure the current
        //random number does not exist in our list
        if(!(numberList.Contains(value)))
        {
            //since it doesnt already exist in our list
            //we can add it to our list
            numberList.Add(value);
        }
    }

    return numberList;
}
apegram 302 LINQ! Team Colleague

HashSet<T> is something that could speed things up here. It was introduced with .NET 3.5, and it's like a dictionary but with a single field instead of a key/value pair, but it is incredibly fast for what you are trying to do due to the way it indexes things (of course, the tradeoff is that it will consume more memory). Just a small change in code, too.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            GenerateRandomNumbers(1, 1000000, 100000);
            stopwatch.Stop();
            Console.WriteLine("GenerateRandomNumbers - {0}ms", stopwatch.ElapsedMilliseconds);
            stopwatch.Reset();


            stopwatch.Start();
            GenerateRandomNumbersFast(1, 1000000, 100000);
            stopwatch.Stop();
            Console.WriteLine("GenerateRandomNumbersFast - {0}ms", stopwatch.ElapsedMilliseconds);
            stopwatch.Reset();

            Console.Read();
        }

        private static List<int> GenerateRandomNumbers(int minValue, int maxValue, int howMany)
        {
            List<int> numberList = new List<int>();
            Random rand = new Random();

            for (int i = 0; i < howMany; i++)
            {
                int value = rand.Next(minValue, maxValue);
                if (!(numberList.Contains(value)))
                {
                    numberList.Add(value);
                }
            }

            return numberList;
        }

        private static List<int> GenerateRandomNumbersFast(int minValue, int maxValue, int howMany)
        {
            HashSet<int> numberList = new HashSet<int>();
            Random rand = new Random();

            for (int i = 0; i < howMany; i++)
            {
                int value = rand.Next(minValue, maxValue);
                if (!(numberList.Contains(value)))
                {
                    numberList.Add(value);
                }
            }

            return numberList.ToList();
        }
    }
}

Run that. On my machine, the first method took over 22 seconds, the second was under 30 milliseconds! I'll take that performance over any memory concerns.

Another alternative, which I thought of before but didn't test until just now, is to not even worry about seeing if the number already exists in the list. Just add it, and then use the .Distinct() extension method before returning the list from the function.

private static List<int> GenerateRandomNumbersFastWithList(int minValue, int maxValue, int howMany)
        {
            List<int> numberList = new List<int>();
            Random rand = new Random();

            for (int i = 0; i < howMany; i++)
            {
                int value = rand.Next(minValue, maxValue);
                numberList.Add(value);
            }

            return numberList.Distinct().ToList();
        }

The above performs comparably with the HashSet version!

commented: some useful additions, i'll be looking into HashSets :) +1
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.