Простой : двойной тип имеет 52 бита с точностью до IEEE. Так что сгенерируйте случайное целое число без знака (52 бита или больше) (например, читая байты из dev / urandom), преобразуйте его в двойное и разделите на 2 ^ (количество битов).
Это дает численно равномерное распределение (в котором вероятность того, что значение находится в данном диапазоне пропорционально диапазону) вплоть до 52-й двоичной цифры.
Сложно : Однако в диапазоне [0,1) существует много двойных значений, которые не могут быть сгенерированы выше. Чтобы быть точным, половина значений в диапазоне [0,0.5) (те, у которых установлен их младший значащий бит) не может появиться. Три четверти значений в диапазоне [0,0.25) (те, у которых установлен хотя бы один из двух младших битов) не могут появиться и т. Д., Причем возможно только одно положительное значение меньше 2 ^ -51, несмотря на то, что двойник способен представлять миллиарды таких ценностей. Таким образом, нельзя сказать, что он действительно однороден в указанном диапазоне с полной точностью.
Конечно, мы не хотим выбирать один из этих двойников с равной вероятностью, потому что тогда результирующее число будет в среднем слишком маленьким. Нам по-прежнему нужно, чтобы вероятность того, что результат находится в данном диапазоне, была пропорциональна диапазону, но с большей точностью определяла, для каких диапазонов это работает.
Я думаю следующие работы. Я не особенно изучал или тестировал этот алгоритм (как вы, вероятно, можете сказать по тому, что кода нет), и лично я бы не использовал его, не найдя правильных ссылок, указывающих на его действительность. Но здесь идет:
- Начните экспоненту с 52 и выберите 52-битное случайное целое число без знака (при условии, что у Мантиссы 52 бита).
- Если старший значащий бит целого числа равен 0, увеличьте показатель степени на единицу, сдвиньте целое число влево на единицу и заполните младший значащий бит новым случайным битом.
- Повторяйте до тех пор, пока вы не достигнете 1 в наиболее значимом месте, иначе показатель не станет слишком большим для вашего двойника (1023. Или, возможно, 1022).
- Если вы нашли 1, разделите ваше значение на 2 ^ экспоненты. Если вы получили все нули, верните 0 (я знаю, это на самом деле не особый случай, но он подчеркивает, насколько маловероятно возвращение 0 [Править: на самом деле это может быть особый случай - это зависит от того, хотите ли вы генерировать или нет) Денормс. Если нет, тогда, когда у вас будет достаточно 0 в ряду, вы отбрасываете все, что осталось, и возвращаете 0. Но на практике это так маловероятно, чтобы быть незначительным, если случайный источник не является случайным).
Я не знаю, есть ли какое-то практическое применение для такого случайного двойника, заметьте. Ваше определение случайного должно зависеть от того, для чего оно. Но если вы можете извлечь выгоду из того, что все 52 его значащих бита являются случайными, это может быть полезно.