Получение случайного вещественного числа в определенном диапазоне с помощью WELL512

Я использую функцию генератора псевдослучайных чисел WELL512, описанную в этой статье. Функция возвращает случайное значение unsigned long.

Как использовать это возвращаемое значение для создания случайного действительного числа в определенном диапазоне, например, с плавающей запятой от 340,92491 до 859812,53198 включительно.

Документация для функции C rand(), кажется, предостерегает от использования mod.


person kobarp    schedule 22.07.2011    source источник


Ответы (3)


Ну, математически это просто:

min_value + (max_value - min_value) * (my_random() / (long double)ULONG_MAX)

(Предполагая, что my_random() возвращает равномерно распределенное число от 0 до ULONG_MAX)

Однако, в зависимости от точных значений min_value, max_value и ULONG_MAX, некоторые числа с плавающей запятой почти наверняка будут более вероятными, чем другие.

Каждая возможная случайная длина без знака отображается в число с плавающей запятой по этой формуле. Но поскольку количество различных чисел с плавающей запятой между min_value и max_value почти наверняка не равно точно ULONG_MAX, некоторые беззнаковые длинные числа будут отображаться в одно и то же число с плавающей запятой, или некоторые числа с плавающей запятой не будут иметь никакого беззнакового длинного сопоставления с ними или с обоими.

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

[редактировать]

Или посмотрите ответ на этот вопрос:

Генерация случайных значений с плавающей запятой на основе случайного битового потока< /а>

Этот ответ зависит от внутреннего устройства представления IEEE double. Я также не уверен, что полностью понимаю, как это работает.

[править 2]

Хорошо, теперь я понимаю, как это работает. Идея состоит в том, чтобы выбрать случайное представление с плавающей запятой между минимумом и максимумом, а затем отбросить его с вероятностью, обратно пропорциональной его масштабу, представленному его показателем степени. Потому что для равномерного распределения числа между (скажем) 1/2 и 1 должны быть вдвое менее вероятными, чем числа между 1 и 2, но количество представлений с плавающей запятой в этих диапазонах одинаково.

Я думаю, вы могли бы сделать этот код более эффективным, если бы сначала выбирали экспоненту в логарифмическом масштабе, например, используя ffs для произвольно выбранного целого числа, а затем выбирали мантиссу случайным образом. Хм...

person Nemo    schedule 22.07.2011

Можно ли преобразовать действительное число в беззнаковое длинное? Если это легко сделать, я думаю, что WELL512 работает. Удачи.

person Summer_More_More_Tea    schedule 22.07.2011

Совершенно просто невозможно представить равномерно распределенные действительные числа с помощью чисел с плавающей запятой - в вашем диапазоне есть неисчислимое бесконечное количество действительных чисел, но только конечное число чисел с плавающей запятой.

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

person caf    schedule 22.07.2011
comment
Не могли бы вы объяснить немного больше о том, что означает граница экспоненты с плавающей запятой? Я не знаком с этим понятием. Спасибо. :-) - person Summer_More_More_Tea; 22.07.2011
comment
@Summer_More_More_Tea: это точка в диапазоне чисел с плавающей запятой, где значение экспоненты изменяется, например, с 1.111....1111 * 2^4 на 1.000....0000 * 2^5. В этот момент разрыв между двумя соседними числами с плавающей запятой удваивается/удваивается. - person caf; 22.07.2011