1

When I run the following code in Mono (and not in Microsoft's C# apparently) in the monodevelop IDE. I get the same sequence of random numbers every time (00111111110110001001). If I change the range to something else e.g. r.Next(0, 5) then I do get random values. This seems very weird to me .. is this a bug or am I doing something dumb?

NOTE: it seems sometimes these numbers are negated.. e.g. I see 11000000001001110110 occasionally.

using System;

namespace TestRNG
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            Random r = new Random ();
            for (int i = 0; i < 20; i++) {
                Console.Write(r.Next(0, 2));
            }
            Console.WriteLine();
        }
    }
}

This is not the "Calling Next() on instances of Random called too closely together and therefore seeded with the same seed from the system clock problem".

Using the following code:

using System;

namespace TestRNG
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            Random r = new Random (Guid.NewGuid().ToByteArray()[0]);
            for (int i = 0; i < 20; i++) {
                int rn = r.Next ();
                Console.WriteLine(rn + " " + (rn % 2));
            }
            Console.WriteLine();
        }
    }
}

I see that I get different values for rn every time but the sequence of values for rn % 2, which is what I suspect r.Next() is returning, is the same old values I always see. This leads me to believe that the Russian? fellow who posted an answer before and was down-voted to oblivion was correct (he's subsequently removed his answer). See http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx for example.

Based on one of the comments below this may only be a mono implementation thing.

demented hedgehog
  • 7,007
  • 4
  • 42
  • 49
  • Running this on Windows yields different sequences of zero and one. – Enigmativity Feb 08 '15 at 03:50
  • Does that happen every time? (ie. are they different each time you run?). Are you running using mono or C#. May be a poor RNG implementation in mono? – demented hedgehog Feb 08 '15 at 04:00
  • No, our Russian friend was wrong. The sequence is obviously not random when you take modulo 2. In other words, the `r.Next()` is giving you a random sequence of bits except for the last bit - the last bit is always predicable. It seems like a mono implementation issue and the code is fine in Windows. – Enigmativity Feb 08 '15 at 04:48
  • I've retagged this from C# to mono and fixed the title so I don't confuse C# people. I've also posted a bug report to mono. I think our Russian friend's point was there was a lack of randomness in the low order bits of the random numbers generated. I suspect that may be the cause here. Actually you may be right about our Russian friend if he used modulo it wouldn't help (I can't recall his name or the exact text he posted). Right shifting does seem to help. – demented hedgehog Feb 08 '15 at 05:20
  • You should add the [c#] tag back in - just because it is [mono] doesn't mean it is not [c#]. [mono] is just the linux implementation of the CLR, which includes [c#]. – Enigmativity Feb 08 '15 at 06:13

2 Answers2

0

Well, extending on what swistak said(because i used the Guid class too), this is the code i made for your issue, is already tested and it works:

using System;
using System.Linq;

namespace pruebaDeNumerosAleatorios
{
class MainClass
{
    public static int RandomNumber()
    {
        Random x = new Random(Guid.NewGuid().ToByteArray().First());
        return x.Next(0, 20);
    }
    public static void Main(string[] args)
    {
        for (int i = 0; i < 20; i++)
            Console.WriteLine(RandomNumber());
    }

}
}

As it was said before, you don't give the time to the internal clock (which you are using as seed) to change between iterations so, the number generated is the same. What i did here is implement the Guid class which generates a 'unique' number, convert it as an array of bytes and just used the first element of the array as seed. i did this in a method because that guarantees me that everytime the method is called a diferent number is generated by the Guid class, so im using a different seed for the random number.

  • You're creating a new Random each time. That's not the way it's supposed to be used I don't believe. – demented hedgehog Feb 08 '15 at 05:02
  • Yes but in terms of memory that wouldn't affect since the scope of the random objects is the method in which i create them. – Rick Guevara Feb 08 '15 at 05:03
  • after returning the random value, the object created is elegible for the garbage collector. – Rick Guevara Feb 08 '15 at 05:04
  • and, if your problem is indeed a monoDevelop issue this could serve as 'workaround' at least :) – Rick Guevara Feb 08 '15 at 05:10
  • All of this is true. But you have the time overhead of allocating and deallocating a potentially large number of random objects. It's doing more work than it needs to. (It's not a monodevelop bug.. possibly a mono bug). – demented hedgehog Feb 08 '15 at 05:13
  • From the ms docs here https://msdn.microsoft.com/en-us/library/system.random%28v=vs.110%29.aspx "Random() Initializes a new instance of the Random class, using a time-dependent default seed value." So it should seed using the system time by default. – demented hedgehog Feb 08 '15 at 05:21
  • Well, what if you make only two Random objects with different seeds and add them while printing them? something like: Console.WriteLine(firstNumber.Next(0,10) + secondNumber.Next(0,10)); //you need to keep in mind that when adding them they dont get out of the max number you want though. That, at least will make it less probable to repeat i guess. – Rick Guevara Feb 08 '15 at 05:23
  • Yeah.. but my problem is that I want to generate random numbers in the range 0-1. Adding two non-random sequences together isn't likely to produce any more randomness I suspect. – demented hedgehog Feb 08 '15 at 05:28
-3

You can generate "more random" number without much higher impact on performance by using Guid class:

Random r = new Random(Guid.NewGuid().ToByteArray()[0]);

Edit: The problem with getting similar values every time is because Random.Next() is taking value from current system clock, so probably there isn't much difference in time between each compilation to generate varied values. Try running your code in a loop and values should be more varied.

swistak
  • 80
  • 4
  • This is not "more" random than before. It's just a different seed. The random number generator hasn't changed. – Enigmativity Feb 08 '15 at 03:53
  • I get a different string using this seed than the implicit system time seed.. but it still repeats for different iterations. Which is what I would expect from picking a different seed. – demented hedgehog Feb 08 '15 at 03:54
  • But by picking random seed, you can get different values every time. Doesn't my example solve this question? – swistak Feb 08 '15 at 03:58
  • @swistak - No, it doesn't. The OP specifically stated that it wasn't a seeding issue. It appears to be a mono implementation issue as the OP's code works fine in Windows. – Enigmativity Feb 08 '15 at 04:01
  • `Random.Next()` does **not** take its values from the system clock. If you instantiate `Random` using the default constructor it gets the seed from the system clock. From that point the values produced are deterministic. – Enigmativity Feb 08 '15 at 04:04