how good is .NET's Random for making random numbers?

Z

Zytan

Anyone do any tests on it? I would assume it has improved since C's
rand(), but who knows. For some reason, and it could just be
coincidence, I seem to see patterns. But even a crappy rand()
function should be good enough to avoid that, so i may be seeing
things.

Zytan
 
M

Marc Gravell

Are you re-using a Randomobject, or creating a new one each time? Note
that the seed is time-based and is not high-def, so if you use new
Random() in a tight loop you will get batches of the same numbers. a
static (locked) Random instance can be useful in some scenarios; I
believe Jon has a StaticRand class (or similar) in his misc.utils. If
you want more "randomness" then use a cryptographic random, which this
isn't. But they are more expensive.

As for patters: over what range? Statistically you simply will see
similar numbers occasionally...

Marc
 
J

Jon Davis

I always create a exactly one single static Random object with my app and
seed it with DateTime.Now.Ticks.

Jon
 
A

Alberto Poblacion

Zytan said:
Anyone do any tests on it? I would assume it has improved since C's
rand(), but who knows. For some reason, and it could just be
coincidence, I seem to see patterns. But even a crappy rand()
function should be good enough to avoid that, so i may be seeing
things.

If the Random class is not good enough for you, you may wish to take a
look at the System.Security.Cryptography.RNGCryptoServiceProvider, which
provides a cryptographically-robust random number generator.
 
J

Jon Skeet [C# MVP]

Jon Davis said:
I always create a exactly one single static Random object with my app and
seed it with DateTime.Now.Ticks.

Random already seeds itself with Environment.TickCount if you don't
provide any constructor parameters.

You need to watch for using a single object in a multi-threaded
situation though - Random isn't thread-safe.
 
J

Jon Davis

Jon Skeet said:
Random already seeds itself with Environment.TickCount if you don't
provide any constructor parameters.

True, but specifying the ticks gives me a stub I can modify later.
You need to watch for using a single object in a multi-threaded
situation though - Random isn't thread-safe.

Since Next() always scrambles its seed, regardless of calling thread, why is
this of concern?

Jon
 
J

Jon Davis

Jon Davis said:
Since Next() always scrambles its seed, regardless of calling thread, why
is this of concern?

Come to think of it, multiple threads are *exactly* the reason why you
should use exactly one static Random in an app, unless you're really trying
to create collisions.

Jon
 
P

Peter Duniho

Anyone do any tests on it? I would assume it has improved since C's
rand(), but who knows. For some reason, and it could just be
coincidence, I seem to see patterns.

Of course you see patterns. You're human, and that's what humans are
designed to do.

I'm reminded of my wife's complaint that one of the games I wrote would
occasionally throw up two or more wild-card pieces in quick succession.
"It's not random enough!" It was a little hard to figure out the best way
to explain that it was doing that exactly because it *was* random. That
if the wild-card pieces only showed up on specific intervals, then *that*
would be an indication of lack of randomness.

Anyway, unless the patterns you see are something like "1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10", you probably are "just seeing things" and I wouldn't worry about it
if I were you. :)

Pete
 
J

Jon Skeet [C# MVP]

Since Next() always scrambles its seed, regardless of calling thread, why is
this of concern?

If Next() is called from two threads at the same time, they could both
get to the "reading" point of the code at the same time, and see the
same value, which probably isn't desirable. If you got two threads in
lock-step they could see the same whole sequence of numbers - unlikely
as

Furthermore, because it's not documented as being thread-safe it
wouldn't be entirely unreasonable for Random to just break in a multi-
threaded situation. I don't think it does in the current
implementation, but I don't like calling things which aren't designed
for multi-threaded use in a multi-threaded way.

My StaticRandom class uses a single Random object, but serializes
access to it. As each call is very fast, it's unlikely that there will
be performance issues and it's just that bit safer. It's also easier
to use from your own code - just call StaticRandom.Next etc :)

Jon
 
J

Jon Davis

Jon Skeet said:
If Next() is called from two threads at the same time, they could both
get to the "reading" point of the code at the same time,

Uhm... I never said one should disregard thread locking.

public static Random AppRandom = new Random();
public static int NextRandom
{
get { lock (typeof(Program)) { return AppRandom.Next(); } }
}
My StaticRandom class ...

Not to shrug off your ever-important opportunity to toot your own horn, my
point is that by sticking to only one static Random in the app you nearly
eliminate the risk of two parallel Random objects ending up with the same
seed or an eventual sequential match of pattern between instances.

Jon
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Zytan said:
Anyone do any tests on it? I would assume it has improved since C's
rand(), but who knows. For some reason, and it could just be
coincidence, I seem to see patterns. But even a crappy rand()
function should be good enough to avoid that, so i may be seeing
things.

Zytan

As mentioned earlier, the most common reason for bad randomness is
creating several Random objects. If used correctly, the randomness is
pretty good.

If you create a very large number of random numbers, you will be able to
see some subtle patterns. If you for example pick colors by random for
every pixel in a large image, your brain will probably be able to
distinguish some patterns, as the random numbers are not completely random.

If you need really really really good randomness, there is a random
generator in the System.Security.Cryptography namespace. It's used to
create encryption keys, where the demands for randomness is extremely high.
 
G

Guest

"The generation of random numbers is far too important to be left to chance"
-- Robert Coveyou
 
A

Alun Harford

Zytan said:
Anyone do any tests on it? I would assume it has improved since C's
rand(), but who knows. For some reason, and it could just be
coincidence, I seem to see patterns. But even a crappy rand()
function should be good enough to avoid that, so i may be seeing
things.

Here are some random numbers:

5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5.

The problem with randomness is that you never can tell.

Alun Harford
 
N

Nicholas Paldino [.NET/C# MVP]

Depending on the distribution you need, if you need a random number
generator which won't be so predictable, you can consider the
RNGCryptoServiceProvider class in the System.Security.Cryptography
namespace. You still have the issues with thread-safety, but you will get a
much more random distribution of numbers.
 
Z

Zytan

Are you re-using a Randomobject, or creating a new one each time? Note
that the seed is time-based and is not high-def, so if you use new
Random() in a tight loop you will get batches of the same numbers.

I should have stated that I wasn't doing this. I create one instance,
using the default time.
As for patters: over what range? Statistically you simply will see
similar numbers occasionally...

It seems that the similar numbers pop up twice in a row sometimes, far
too often. Yes, I know this should happen, but without going and
making a test to see how random it is, I was wondering if it was
already done. I want to know if it's better than C's rand().

Zytan
 
Z

Zytan

Furthermore, because it's not documented as being thread-safe it
wouldn't be entirely unreasonable for Random to just break in a multi-
threaded situation. I don't think it does in the current
implementation, but I don't like calling things which aren't designed
for multi-threaded use in a multi-threaded way.

If they implemented any of the more complicated multi-dimension random
number generators that stores huge arrays of information, that are
incrementally indexed, you'll eventually find that the index is
increased twice on the last element (from two different threads) and
it will crash. NET could potentially improve Random() to use such an
algorithm, and you would have to say byebye to your code.
My StaticRandom class uses a single Random object, but serializes
access to it. As each call is very fast, it's unlikely that there will
be performance issues and it's just that bit safer. It's also easier
to use from your own code - just call StaticRandom.Next etc :)

Thanks, I'll have to take a look at this.

Zytan
 
J

Jon Skeet [C# MVP]

Uhm... I never said one should disregard thread locking.

I must have misinterpreted you then. I wrote:

<quote>
You need to watch for using a single object in a multi-threaded
situation though - Random isn't thread-safe.
</quote>

and you responded:

<quote>
Since Next() always scrambles its seed, regardless of
calling thread, why is this of concern?
</quote>

I hope you can see why I interpreted this as effectively disregarding
the fact that Random isn't thread-safe.
public static Random AppRandom = new Random();
public static int NextRandom
{
get { lock (typeof(Program)) { return AppRandom.Next(); } }

}

Not to shrug off your ever-important opportunity to toot your own horn, my
point is that by sticking to only one static Random in the app you nearly
eliminate the risk of two parallel Random objects ending up with the same
seed or an eventual sequential match of pattern between instances.

Leaving the personal attack to one side (any reason for that, by the
way? I'll readily admit there's nothing remotely clever in
StaticRandom - it's just handy to not have to reinvent the wheel,
that's all) I quite agree that using a static Random object is a good
idea, otherwise I wouldn't have written StaticRandom in the first
place.

All I said to start with is that you need to be careful. Clearly in
your code you *are* being careful (by locking) so I'm not sure what
the fuss is about.

Jon
 
Z

Zytan

my
point is that by sticking to only one static Random in the app you nearly
eliminate the risk of two parallel Random objects ending up with the same
seed or an eventual sequential match of pattern between instances.

Yes, that's true.

Zytan
 
Z

Zytan

If the Random class is not good enough for you, you may wish to take a
look at the System.Security.Cryptography.RNGCryptoServiceProvider, which
provides a cryptographically-robust random number generator.

Ok, thanks, Alberto. I don't need it to be secure, though, just more
random. But, this would suit that purpose, as well.

Zytan
 
Z

Zytan

Anyway, unless the patterns you see are something like "1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10", you probably are "just seeing things" and I wouldn't worry about it
if I were you. :)

I am 99.9% sure you are right, and i think the same thing, but I still
just want to know if it's better than the 3 lines of code C's rand()
was made from, since with extremely little effort, you could see
patterns. Not like the above, but when shown in a visual way, where
you can 'see' the numbers' meanings (not their digits), you could see
the same stuff occured over and over again. Especially if you made
sure to sequence them in groups of even binary numbers ;)

Zytan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top