На самом деле, у меня есть несколько взаимосвязанных вопросов. (Если это имеет значение, я использую C#.)
Первый. У меня есть prng, который генерирует случайные числа в диапазоне UInt32, от 0 до UInt32.Max включительно. Я хочу максимально сохранить единообразие. Какова основная идея получения [a,b], (a,b) двойных диапазонов (например, [0,1], [0,1), (0,1), [-2,4], (- 10,10))?
Меня беспокоит следующее. У меня есть 4 294 967 296 исходов prng. Чисел в двойном диапазоне [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 равномерна?
Спасибо.