На самом деле, у меня есть несколько вопросов переплетения. (Если это имеет значение, я использую C #.)
Во-первых. У меня есть prng, который генерирует случайные числа в диапазоне UInt32, от 0 до UInt32.Max включительно. Я хочу максимально сохранить однородность. Какова основная идея получить [a, b], (a, b) двойные диапазоны (такие как [0,1], [0,1), (0,1), [-2,4], (- 10,10?))
Меня беспокоит следующее. У меня 4 294 967 296 результатов. Меньше чисел в [0,1] двойном диапазоне - 2 ^ 53. Поэтому я строю 4 294 967 296-иное число из 2 цифр, которое является случайным и единообразным в [0, 4294967295 * 4294967296 + 4294967295]. Это максимальное значение больше, чем 2 ^ 53 на 1, поэтому, если вы его получите, выкините его, пересчитайте, используйте мод 2 ^ 53 и получите равномерное число, например, [0,1]. Здесь я должен представить максимальное значение как double (предположим, что нет типа Int64) - есть ли у него недостатки?
Теперь, если я хочу получить [0,1), я считаю, что число результатов равно (2 ^ 53) - 1. Добавление к последнему результату 1 / (2 ^ 53) приведет к случайному удвоению в (0 , 1]. Чтобы получить (0,1), я рассматриваю (2 ^ 53) - 2 новых результата и добавляю 1 / (2 ^ 53) к результату на основе 0. Это все правильно?
Но как получить двойные диапазоны, близкие или равные всему двойному диапазону? Даже если я построю n-арное число, как указано выше, оно может стать больше, чем Double.Max. Может быть, возможен какой-то подход бит-сдвигов / бит-масок?
Во-вторых. Теперь есть двойной prng с результатами в [0,1), возможно ли получить диапазон [Double.Min, Double.Max]? Сколько всего двойных чисел? Если есть полный двойной диапазон prng, каков наилучший способ получить диапазон UInt - отобразить «напрямую» или масштабировать до [0,1] раньше?
В-третьих. Я нашел этот код (http://www.math.sci.hiroshima -u.ac.jp / ~ m-mat / MT / MT2002 / CODES / mt19937ar.c):
/* generates a random number on [0,1) with 53-bit resolution*/
double genrand_res53(void)
{
unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
return(a*67108864.0+b)*(1.0/9007199254740992.0);
}
Почему a и b сдвинуты на 5 и 6 и почему после этого a * 67108864.0 + b является однородным?
Спасибо.