Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate a cryptographically secure Double between 0 and 1?

Tags:

c#

random

I know how to generate a random number between 0 and 1 using the NextDouble method of the pseudo-random number generator.

var rng1 = new System.Random();
var random1 = rng1.NextDouble(); // generates a random double between 0 and 1.0

And I know how to fill a random byte array using the cryptographically secure random number generator.

Byte[] bytes = new Byte[8];
var rng2 = new System.Security.Cryptography.RNGCryptoServiceProvider();
rng2.GetBytes(bytes); // generates 8 random bytes

But how can I convert the byte-array output of RNGCryptoServiceProvider into a random number uniformly distributed between 0 (inclusive) and 1 (exclusive)?

like image 563
Portman Avatar asked May 18 '10 03:05

Portman


1 Answers

It appears to me that the solutions so far will have uneven distribution due to taking the inverse. For an even distribution I'd think you want something like this.

// Step 1: fill an array with 8 random bytes
var rng = new RNGCryptoServiceProvider();
var bytes = new Byte[8];
rng.GetBytes(bytes);
// Step 2: bit-shift 11 and 53 based on double's mantissa bits
var ul = BitConverter.ToUInt64(bytes, 0) / (1 << 11);
Double d = ul / (Double)(1UL << 53);

Note that you can't just divide the UInt64 into UInt64.MaxValue, because a double doesn't have enough bits, and there's no way to get unique outputs for all your inputs. So you can/must throw some bits away.

like image 59
Conrad Albrecht Avatar answered Oct 07 '22 01:10

Conrad Albrecht