Ну, математически это просто:
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, но число представлений с плавающей точкой в этих диапазонах одинаково.
IЯ думаю, что вы могли бы сделать этот код более эффективным, сначала выбрав экспоненту в логарифмическом масштабе - скажем, используя ffs
для случайно выбранного целого числа - и затем выбрав мантиссу случайным образом.Хм ...