Reputation: 340
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
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
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
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