Half_Baked
Half_Baked

Reputation: 340

C# Get only numbers 1-15 from RNGCryptoServiceProvider?

As RNGCryptoServiceProvider is "safer" (produces high-quality random numbers) than Random() I felt for using it. Performance is not an issue. But, instead of reading the last digit, and somehow decide when to add a 0 or 1 before it.. Is there a better (more accurate) way?

byte[] data = new byte[4];
rng.GetBytes(data);
int value = BitConverter.ToInt32(data, 0);
Console.WriteLine(value);

Upvotes: 4

Views: 4049

Answers (3)

Michal Hanko
Michal Hanko

Reputation: 1

It's easy:

static int getnum15(RNGCryptoServiceProvider RngCsp)
{
    byte[] p=new byte[1];
    do {
        RngCsp.GetBytes(p);
    } while (p[0]==255);
    return(p[0]%15);
}

because 256 mod 15=1. Then

RNGCryptoServiceProvider rngCsp=new RNGCryptoServiceProvider();
for (int i=0;i<30;i++)
    Console.WriteLine(getnum15(rngCsp));

Upvotes: 0

CodesInChaos
CodesInChaos

Reputation: 108830

You can use the modulo operator (%). This leads to slightly biased results, but with an 8 byte input the bias is quite small. Much smaller than the bias System.Random has.

byte[] data = new byte[8];
rng.GetBytes(data);
ulong value = BitConverter.ToUInt64(data, 0);
result = (int)(value%15+1);

Or if you want perfectly uniform numbers:

byte[] data = new byte[8];
ulong value;
do
{
    rng.GetBytes(data);
    value = BitConverter.ToUInt64(data, 0);
} while(value==0);
result = (int)(value%15+1);

Upvotes: 8

Jonny
Jonny

Reputation: 1483

There is no way to make the RNGCryptoServiceProvider give you numbers, because it is not intended for arithmetics. In cryptography, you work with words and bytes. If want a different RNG for arithmetic purposes, pick a different library.

Upvotes: -2

Related Questions