Сгенерировать случайное двойное число в диапазоне [0, 1] в C - PullRequest
0 голосов
/ 26 мая 2020

Мне нужно сгенерировать случайное двойное число от 0 до 1. Как это сделать с помощью C? Я попытался сгенерировать целое число от 0 до миллиона, а затем разделить результат на 1M, но это не сработало.

Ответы [ 2 ]

4 голосов
/ 26 мая 2020

генерировать случайное двойное число от 0 до 1

Некоторые моменты, которые следует учитывать:

Включить 1.0 ??

Я бы ожидал, что цель будет «в диапазоне [0, 1)», а не «в диапазоне [0, 1]». Включение 1.0 создает сложности, поскольку разбалансирует распределение. Предположим, [0, 1).

rand() Качество

rand() имеет неопределенное качество, и его диапазон [0 ... RAND_MAX] может не end 1 меньше степени двойки. Предположим, что rand() достаточно на данный момент, а RAND_MAX - это число Мерсенна (что очень часто), чтобы облегчить объединение нескольких вызовов rand() с простым ^.

Маленькие числа

Около половины всех положительных double меньше 1,0. Должны ли все они иметь шанс?

Типичность DBL_MANT_DIG 53 и поэтому:

В [0.5 ... 1.0).
Есть 2 52 double значений в диапазоне [0,25 ... 0,5).
Есть 2 52 double значений в диапазон [0,125 ... 0,25).
...

Нам нужен 50% шанс значения из первой группы, 25% из следующей, 12,5% из следующей .. ..?

Или удовлетворены:

Форма 2 53 double значения в диапазоне [0,0 ... 1,0) равномерно распределены?


Давайте сейчас go для второй цели - проще кодировать.

Сгенерировать целое число double в диапазоне [0 ... 2 53 ) а затем разделить на 2 53 .

RAND_MAX >= 0x7FFF по определению, чтобы мы получили не менее 15 бит случайных битов.

Ниже приведен пример кода, который, а не так эффективно формирует double [0,0 ... 1,0).

// Illustrative code
double rand_double_01(void) {
  unsigned long long r = 0;
  #define RANDOM_BITS 15
  for (int i = 0; i < DBL_MANT_DIG; i += RANDOM_BITS) {
    r <<= RANDOM_BITS;
    r ^= rand();
  }
  r %= 1uLL << DBL_MANT_DIG;   // Mask off lower 53 bits
  double dr = r; // expected conversion is exact
  // scale [0 ... 1.0)
  double dr /= 1uLL << DBL_MANT_DIG;  // expected conversion/quotient exact 
  return double dr; 
}

Примечание. Приведенный выше код может завершиться ошибкой, если DBL_MANT_DIG >= 64 (не часто) или * 1 078 * (очень редко).

1 голос
/ 26 мая 2020

Будьте осторожны при делении чисел: когда оба числа являются целыми числами, будет использоваться целочисленное деление (в этом случае всегда получается ноль).

Чтобы в результате получилось двойное число, вам необходимо заставить деление быть делением на двойные, чего можно добиться, задав одно из чисел как двойное:

a/b => integer division (when b is larger than a you end up with zero)

((double)a/b) => floating point division (this is what you are looking for)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...