2

I am not sure if any language(preferably C# .NET) supports non-uniform random number generator. Is there any? I was wondering what could be the best design approach to implement our own non-uniform random number generator?

Thanks.

skaffman
  • 398,947
  • 96
  • 818
  • 769
Paresh Masani
  • 7,474
  • 12
  • 73
  • 139
  • I found some of the implementation and design concept at http://stackoverflow.com/search?q=non-uniform+random+numbers+generator This one is best: http://stackoverflow.com/questions/1534285/non-uniform-random-number-generator-implementation . None of them say if any language is already supporting non-uniform random number generator. – Paresh Masani Mar 18 '11 at 13:45
  • C# doesn't support random-number generation at all, it's the BCL that offers it. To answer your question though, we'd need to know what way you want it to be non-uniform; bell-curve, or something else? – Jon Hanna Mar 18 '11 at 14:01
  • Thanks Job. What is BCL? I have used C# random number generator but it always be an uniform. If I generate millions of numbers between 1-100, individual counts for each number coming almost same. I want the selection to be totally non-uniform so it might be possible that some numbers are not picked up at all and some numbers counter might be far ahead of compare to others. I mean there shouldn't be any priority or dependency in selection of next number. – Paresh Masani Mar 18 '11 at 15:09
  • I know that C# and almost all language's random number generator are dependent of the current timestamp of system or the seed you specify. So if you give the fix timestamp then every time it will generate the same numbers. I want my numbers to be totally independent. – Paresh Masani Mar 18 '11 at 15:11
  • 1
    From the sound of it, what you're looking for is uniform (each number has an equal chance of being picked), but isn't pseudo-random, but rather based on true randomness. That can't quite be done; recording sources of randomness like difference between key-stroke time gives a reasonably good way that may serve many cases, but otherwise you need hardware or an external source of random data. – Jon Hanna Mar 18 '11 at 15:34

2 Answers2

4

Well, it’s 2016, this question has no points, and already has an accepted answer. But since, it came up second when I googled “c# random non uniform”, I’ll go ahead and give my approach.

Before starting, you have to consider what kind of non-uniform distribution you want. In my case, I needed most numbers to be low, while a few should be high. For any distribution, we need only consider numbers between 0 and 1 (so properties outside that range are irrelevant). The result can be multiplied or otherwise manipulated to fit any desired range. In the end, (x-1)^4 worked for me. It has a value of 1 when x = 0, a value of 0 when x = 1, but is on average more likely to be low than high.

(x-1)^4

In C#, the generator of the Random class only produces integers. So the first step is to convert it so that it instead produces a rational number between 0 and 1.

var rnd = new Random();
var x = (double)rnd.Next(0,10000) / 10000;

Then, simply plug the random number into the distribution you desired.

x = Math.Pow(x-1,4);

I created a list of randomly generated numbers with this method and got the following result (sorted and rounded):

0
0.0001
0.0109
0.0115
0.042
0.1615
0.3077
0.5713
0.7217
0.8087

As you can see, the distribution is not uniform: it has a bias toward 0, but can still take on exactly 0 or 1 as a value.

Because of the implications when searching for answers on SO, I’m answering the question as asked. But in @applefreak's comments to his own question, it seems that he may also/instead be looking for a truly, non-pseudo-random number generator. @JonHanna’s response that “that can’t quite be done” is then appropriate. Using a source external to the computer may eliminate the dependency on the time-clock, but it still won't be truly random. You could argue that nothing truly is, but that's a question of philosophy.

pwilcox
  • 5,542
  • 1
  • 19
  • 31
1

I was able to created semi non uniform distribution using uniform distribution for my requirements. Basically I generate the required M numbers from 1 to N range and then again just generate (N-M) numbers and throw them away. Like this way when I generate next set of numbers, I get almost equal probability for all numbers between 1 to N. It worked for me!

Example code in C#:

        int low=1, high=50;
        Random random = new Random();
        int total = 50;
        ArrayList set_nos = new ArrayList();

        while (--total > 0)
        {
            int set = 6;
            int loop = 0;
            while (--set > 0)
            {
                int temp = random.Next(low, high);
                loop++;
                if (set_nos.Contains(temp))
                    continue;

                set_nos.Add(temp);
            }

            for (int unused = 1; unused < high-loop; unused++)
                random.Next(low, high);

            //Use set_nos for your purpose!

        }
Paresh Masani
  • 7,474
  • 12
  • 73
  • 139