генерировать случайное двойное число от 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 * (очень редко).