Как генерировать, криптографически защищают Дважды между 0 и 1?

Я знаю, как генерировать случайное число между 0 и 1 использованием метода NextDouble генератора псевдослучайного числа.

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

И я знаю, как заполнить случайный массив байтов с помощью криптографически безопасного генератора случайных чисел.

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

Но как я могу преобразовать вывод массива байтов RNGCryptoServiceProvider в случайное число, равномерно распределенное между 0 (содержащий) и 1 (эксклюзивный)?

13
задан Portman 18 May 2010 в 05:02
поделиться

2 ответа

Мне кажется, что решения, полученные до сих пор, будут иметь неравномерное распределение из-за взятия обратной величины. Для равномерного распределения я бы подумал, что вам нужно что-то вроде этого.

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

Обратите внимание, что вы не можете просто разделить UInt64 на UInt64.MaxValue, потому что у double недостаточно битов, и нет способа получить уникальные выходы для всех ваших входов. Поэтому вы можете/должны отбросить некоторые биты.

24
ответ дан 1 December 2019 в 21:37
поделиться

Что ж, я бы не назвал 64-битное случайное число «криптографически безопасным» - вам нужно гораздо больше битов, чем это, чтобы быть «криптографически безопасным». Но в любом случае вы можете сделать что-то вроде этого:

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

long l = BitConverter.ToInt64(bytes);
double d = Math.Abs(1 / (double)l);
1
ответ дан 1 December 2019 в 21:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: