views:

382

answers:

5

How can I make a fast RNG (Random Number Generator) in C# that support filling an array of bytes with a maxValue (and/or a minValue)? I have found this http://www.codeproject.com/KB/cs/fastrandom.aspx but doesn't have these feature.

A: 

You could use Reflector to decompile System.Random to C#. That would give you the C# code of a fast random number generator that fulfills your requirements.

Freed
Actually, no...the Framework is precompiled and optimized, you can't compete with that (until you also precompile your code). At least that's the experience I made (while trying to outrun the framework ;) ).
Bobby
And why exactly would he do that? Presumably, since he asks, Random is too slow, otherwise he would use that, no?
Lasse V. Karlsen
@Bobby: depressingly, true. Precompiling own code won’t help, though.
Konrad Rudolph
And all I wanted was to hint at using System.Random (directly). I guess I should know better than thing people would detect sarcasm on the Internet... =)
Freed
@Freed, Oh...I think the answer just sounded way to seriously, and had the undertone of "And then you can modify it so it is faster" with it.
Bobby
System.Random isn't a great RNG but a general purpose (and simple) RNG. There is nothing to reuse from it.
tazzo
+15  A: 

System.Random is fast enough for just about any typical use. If you're having performance issues with code that contains System.Random calls, make sure you profile your code before trying to build a new Random. Chances are your performance issues are not in the framework, but rather in your own code.

If you're calling into Random in a loop, make sure you're not creating a new Random instance with each iteration, but instead are re-using a common Random instance. Doing this will improve performance because you aren't creating new objects for the GC to clean up, and will also improve the quality of the random numbers being generated.

Erik Forbes
My code has only to generate many many random numbers in few seconds
tazzo
It's amazing how many of SO answers decide to argue about the needs of the asker instead of answering the question.
Nosredna
@tazzo: how many is many? what are the specific requirements you're after? @Nosredna: sometimes answering the question and helping the asker are two different things. And who's arguing?
Erik Forbes
Answering the question also answers it for the people in the future who actually need _faster_.
Nosredna
many is more than 10^9
tazzo
A: 

use the cryptographic services....

RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
byte[] bytes= new byte[5];
crypto.GetBytes(bytes);

of course, this only satisfies the byte area requirement...

Muad'Dib
I haven't timed it myself, but I would guess that the RNGCryptoServiceProvider, having the extra property of being cryptographically safe, would be slower than System.Random.
Freed
I've checked RNGCryptoServiceProvider but doesn't fit my needs, is to slow and don't let a maximum into random numbers generated.
tazzo
+7  A: 

The fact that you're filling bytes with integers is different enough from the typical usage case for System.Random that you can probably beat it badly if you really need to.

System.Random is made for general use. (In fact, I usually find system random routines uninspiring when I do speed and distribution tests on them.) There are cases where you'd want something else. But you have to be very explicit about your needs. How fast? What are you willing to give up?

If you really need "fast," Marsaglia has produced a number of very fast random number generators that could be adapted to your needs. Here's one:

http://en.wikipedia.org/wiki/Xorshift

The Diehard tests are interesting.

Agner has C++ code for many fast randoms.

Here's a fast twister that uses SIMD instructions.

None of these address the fact that you are targeting bytes. I can think of some pretty fast ways to do that. Elbow grease required if you really want to take advantage of that fact.

I've only needed super fast randoms a few times. In console games with slow processors where random could make the difference between hitting the frame rate target and not hitting it. What is your use case? By all means, use System.Random if you can.

Or, adapt the routine you link to in your question (which the author claims is 8x the speed of System.Random.)

Nosredna
That last link was quite interesting to examine, +1
David Hay
Thank you for your answer, the RNG must be as fastest as possible, I have many many random numbers to generate in few seconds (10^9 and more).I've tried to adapt routine in my link but i've not succed, can you help me?
tazzo
There are many possibilities. Imagine that you've set up a 4k buffer of random numbers for a range (say, 0-100). Use a random number generator to choose an offset and grab, say 16 bytes from your list. Then generate another offset and grab another 16 bytes. This won't be _fantastically_ random, but it may be _sufficiently_ random. Despite my asking, you haven't told me what you're willing to give up to get the speed. What will you be doing with all these numbers?
Nosredna
The numbers are for some test and haven't to be 100% random
tazzo
Well, then I think what I suggested would work great.
Nosredna
A: 

If you have a random number generator that returns numbers from the unit interval, like the one in the Code Project article you mentioned, then you can first generate a value u using that generator and then return a + (b-a)*u to get values between a and b.

John D. Cook
Your formula is incorrect, if I choose A=5 and B=20 and U=55 I get 5+(20-5)*55=830.The right formula is U/(UMAX+1)*(B-A)+A where UMAX is the maximum value of random number.
tazzo
If the random value u comes from the *unit interval*, i.e. between 0 and 1, then the formula is correct. In your example, u = 55 is not a number between 0 and 1.
John D. Cook