Question Comment générer un Double cryptographiquement sécurisé entre 0 et 1?


Je sais comment générer un nombre aléatoire entre 0 et 1 en utilisant le NextDouble méthode du générateur de nombres pseudo-aléatoires.

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

Et je sais comment remplir un tableau d'octets aléatoires en utilisant le générateur de nombres aléatoires sécurisé sur le plan cryptographique.

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

Mais comment puis-je convertir la sortie du tableau d'octets de RNGCryptoServiceProvider en un nombre aléatoire uniformément réparti entre 0 (inclus) et 1 (exclusif)?


11
2018-05-18 03:45


origine


Réponses:


Il me semble que les solutions actuelles auront une distribution inégale en raison de l'inverse. Pour une distribution égale, je pense que vous voulez quelque chose comme ça.

// 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);

Notez que vous ne pouvez pas simplement diviser l'UInt64 en UInt64.MaxValue, car un double n'a pas assez de bits, et il n'y a aucun moyen d'obtenir des sorties uniques pour toutes vos entrées. Donc, vous pouvez / devez jeter des morceaux.


21
2018-05-18 04:50



Eh bien, je n'appellerais pas un nombre aléatoire de 64 bits "cryptographiquement sécurisé" - vous voudriez que beaucoup plus de bits soient "cryptographiquement sécurisés". Mais de toute façon, vous pourriez faire quelque chose comme ceci:

var bytes = // assume this contains 8 bytes of random numbers

long l = BitConverter.ToInt64(bytes);
double d = Math.Abs(1 / (double)l);

1
2018-05-18 03:49