Как вручную генерировать случайные числа

Я хочу генерировать случайные числа вручную. Я знаю, что на каждом языке есть ранды или случайные функции, но мне любопытно знать, как это работает. У кого-нибудь есть код для этого?

Ответы

Ответ 2

POSIX.1-2001 дает следующий пример реализации rand() и srand(), возможно, полезный, когда нужна одна и та же последовательность на двух разных машинах.

static unsigned long next = 1;
/* RAND_MAX assumed to be 32767 */
int myrand(void) {
    next = next * 1103515245 + 12345;
    return((unsigned)(next/65536) % 32768);
}
void mysrand(unsigned seed) {
    next = seed;
}

Ответ 3

Я предполагаю, что вы имеете в виду псевдослучайные числа. Самый простой, который я знаю (от написания игр с видеоиграми на старых машинах), работал следующим образом:

= семян семян * 5 + 1;

Вы делаете это каждый раз, когда вызывается случайный вызов, а затем вы используете как можно больше низких бит. * 5 + 1 имеет приятное свойство (IIRC), чтобы поразить все возможности до повторения, независимо от того, сколько бит вы смотрите.

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

Сделайте пару подобных вещей параллельно и объедините результаты. Это линейный конгруэнтный генератор.

Ответ 5

Алоха!

В ручном режиме вы имеете в виду "не использовать компьютер" или "написать собственный код"?

ЕСЛИ он не использует компьютер, вы можете использовать такие вещи, как кости, цифры в сумке и все те методы, которые видны по телевизору, когда они выбирают команды, выигрывают серии Bingo и т.д. Лас-Вегас заполнен такими методами, которые используются в процессах ( игры), направленные на то, чтобы дать вам плохие шансы и рентабельность инвестиций. Вы также можете получить большую книгу RAND и перейти на случайно выбранную страницу:

http://www.amazon.com/Million-Random-Digits-Normal-Deviates/dp/0833030477

(Кроме того, для некоторых развлечений ознакомьтесь с отзывами)

Для написания собственного кода вам нужно учитывать, почему не использовать систему, предоставляемую RNG, недостаточно. Если вы используете современную ОС, у нее будет доступный RNG для пользовательских программ, которые должны быть достаточно хороши для вашего приложения.

Если вам действительно нужно реализовать свои собственные, существует огромное количество генераторов. Для небезопасного использования вы можете посмотреть цепи LFSR, конгруэнтные генераторы и т.д. Независимо от того, какое распределение вам необходимо (равномерный, нормальный, экспоненциальный и т.д.), Вы должны иметь возможность находить описания алгоритмов и библиотеки с реализациями.

Для обеспечения безопасности вы должны смотреть на такие вещи, как Yarrow/Fortuna, NIST SP 800-89, указанные PRNG и RFC 4086, для хороших источников энтропии, необходимых для подачи PRNG. Или еще лучше, используйте тот, который находится в ОС, который должен соответствовать требованиям безопасности RNG.

Внедрение ГСЧ может быть интересным упражнением, но очень редко необходимо. И не изобретайте свой собственный алгоритм, если он не предназначен для игрушечных приложений. НЕ повторяйте НЕ изобретать RNG для приложений безопасности (например, генерировать криптографические ключи), по крайней мере, если вы не прочитаете и не просмотрите серипус. Вы поблагодарите меня за это (надеюсь).

Ответ 6

    static void Main()
    {
        DateTime currentTime = DateTime.Now;

        int maxValue = 100;

        int hour = currentTime.Hour;
        int minute = currentTime.Minute;
        int second = currentTime.Second;
        int milisecond = currentTime.Millisecond;

        int randNum = (((hour + 1) * (minute + 1) * (second + 1) * milisecond) % maxValue);

        Console.WriteLine(randNum);

        Console.ReadLine();
    }

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

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

Переменные часа, минуты, секунды и милисекунды разбивают значение времени даты на его составные части. Нас интересуют только эти части, поэтому можно игнорировать день. Опять же, в большинстве языков даты и время обычно представлены в виде строк. В .Net у нас есть возможности, позволяющие легко анализировать эту информацию. Но в большинстве других языков, где времена представлены в виде строк, не слишком сложно разобрать строку для тех частей, которые вы хотите, и преобразовать их в свои числа. Эти объекты обычно предоставляются даже на самых старых языках.

Семя существенно дает нам начальный номер, который всегда меняется. Традиционно вы просто умножаете это число на десятичное значение от 0 до 1, это отсекает этот шаг.

Верхний диапазон определяет максимальное значение. Таким образом, число сгенерированных никогда не будет выше этого значения. Также он никогда не будет ниже 0. Так что никаких ньюгейтов. Но если вы хотите негативы, вы можете просто отменить это вручную. (путем умножения на -1)

Действительная переменная randNumis, которая содержит интересующее вас случайное значение.

Трюк состоит в том, чтобы получить остаток (модуль) после деления семени на верхний диапазон. Остаток всегда будет меньше, чем делитель, который в этом случае равен 100. Простые математики говорят вам, что вы не можете иметь остаток больше дивизора. Итак, если вы разделите на 10, у вас нет остатка больше 10. Это простой закон, который дает нам наше случайное число от 0 до 100 в этом случае.

Консоль .writeline просто выводит ее на экран.

Консоль .readline просто приостанавливает программу, чтобы вы могли ее видеть.

Это очень простой фрагмент кода для генерации случайных чисел. Если вы запускаете эту программу с той же самой интервал каждый день (но вам нужно будет делать это в один и тот же час, минуту, секунду и milisecond) в течение более 1 дня, вы начнете генерировать одинаковый набор чисел снова и снова дополнительный день. Это связано с тем, что оно привязано к времени. Это разрешение генератора. Поэтому, если вы знаете код этой программы и время ее запуска, вы можете предсказать число сгенерированных, но это будет нелегко. Вот почему я использовал милисекунды. Используйте секунды или минуты, чтобы увидеть, что я имею в виду. Таким образом, вы можете написать таблицу, показывающую, когда 1 входит, 0 выходит, когда 2 идет в 0 выходит и так далее. Затем вы можете прогнозировать вывод на каждую секунду и диапазон чисел. Чем больше вы увеличиваете разрешение (увеличивая число, которое изменяется), тем сложнее оно и тем больше времени требуется, чтобы получить предсказуемый шаблон. Этот метод достаточно хорош для большинства людей.

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

Надеюсь, это разумный ответ на ваш вопрос.

Ответ 7

hopefuly im не избыточно, потому что я havent читал все ссылки, но я считаю, что вы можете приблизиться к true случайному генератору. в наши дни системы часто настолько сложны, что даже самые лучшие вундеркинды требуют много времени, чтобы понять, что происходит внутри:)

просто откройте свой разум и подумайте, можете ли вы контролировать какое-либо глобальное системное свойство, использовать его для семян... выбрать сетевой пакет (не предназначенный для вас?) и вычислить "что-то" из его содержимого и использовать его для семян... и т.д.


вы можете создать лучшее для своих нужд со всеми эти подсказки вокруг;)

Ответ 8

Mersenne twister имеет очень длительный период (2 ^ 19937-1).

Вот очень простая реализация в С++:

struct MT{
    unsigned int *mt, k, g;
    ~MT(){ delete mt; }
    MT(unsigned int seed) : mt(new unsigned int[624]), k(0), g(0){
        for (int i=0; i<624; i++)
            mt[i]=!i?seed:(1812433253U*(mt[i-1]^(mt[i-1]>>30))+i);
    }
    unsigned int operator()(){
        unsigned int q=(mt[k]&0x80000000U)|(mt[(k+1)%624]&0x7fffffffU);
        mt[k]=mt[(k+397)%624]^(q>>1)^((q&1)?0x9908b0dfU:0);
        unsigned int y = mt[k];
        y ^= (y >> 11);
        y ^= (y << 7) & 0x9d2c5680U;
        y ^= (y << 15) & 0xefc60000U;
        y ^= (y >> 18);
        k = (k+1)%624;
        return y;
    }
};

Ответ 9

Одним из хороших способов получить случайные числа является мониторинг окружающего уровня шума, проходящего через ваш компьютерный микрофон. Если вы можете получить драйвер (или язык, поддерживающий вход микрофона) и преобразовать его в число, вы уже в пути!

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

Вы можете найти эту статью в вики для получения дополнительной информации о науке о генерации случайных чисел.

Ответ 10

Если вы ищете теоретическое лечение случайных чисел, возможно, вы можете взглянуть на Том 2 "Искусство компьютерного программирования". В нем есть глава, посвященная случайным числам. Посмотрите, поможет ли вам это.

Ответ 11

Если вы хотите вручную, жесткий код, свой собственный случайный генератор, я не могу дать вам эффективности, однако я могу дать вам надежность. Я на самом деле решил написать некоторый код, используя время, чтобы проверить скорость обработки компьютера, посчитав во времени, и это превратило меня в мой собственный генератор случайных чисел, используя алгоритм подсчета для modulo (счетчик случайный). Пожалуйста, попробуйте это для себя и проверьте распределение чисел в рамках большого теста. Кстати, это написано на питоне.

def count_in_time(n):
   import time
   count = 0
   start_time = time.clock()
   end_time = start_time + n
   while start_time < end_time:
       count += 1
       start_time += (time.clock() - start_time)
   return count


def generate_random(time_to_count, range_nums, rand_lst_size):
    randoms = []
    iterables = range(range_nums)
    count = 0
    for i in range(rand_lst_size):
        count += count_in_time(time_to_count)
        randoms.append(iterables[count%len(iterables)])
    return randoms

Ответ 12

Этот документ - очень хорошая запись генерации псевдослучайных чисел и включает в себя ряд подпрограмм (в C). В нем также обсуждается необходимость в соответствующем посеве генераторов случайных чисел (см. Правило 3). Особенно полезной для этого является использование/dev/randon/(если вы работаете на Linux-машине).

Примечание. Подпрограммы, включенные в этот документ, alot проще для кода, чем Mersenne Twister. См. Также генератор WELLRNG, который должен иметь лучшие теоретические свойства в качестве альтернативы MT.

Ответ 13

Прочитайте книгу случайных чисел rands (книга monte carlo случайных чисел), числа в ней случайным образом созданы для вас!!! Мой дедушка работал на ранда.

Ответ 14

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

    /// <summary>
    /// Initializes the number array from a seed provided by <paramref name="seed">seed</paramref>.
    /// </summary>
    /// <param name="seed">Unsigned integer value used to seed the number array.</param>
    private void Initialize(uint seed)
    {
        this.randBuf[0] = seed;
        for (uint i = 1; i < 100; i++)
        {
            this.randBuf[i] = (uint)(this.randBuf[i - 1] >> 1) + i;
        }
    }

Это вызывается из конструктора класса рандомизации. Теперь реальные случайные числа могут быть свернуты/вычислены с использованием вышеупомянутых высеваемых значений. Обычно здесь применяется алгоритм рандомизации. Вот еще один пример:

    /// <summary>
    /// Refreshes the list of values in the random number array.
    /// </summary>
    private void Roll()
    {
        for (uint i = 0; i < 99; i++)
        {
            uint y = this.randBuf[i + 1] * 3794U;
            this.randBuf[i] = (((y >> 10) + this.randBuf[i]) ^ this.randBuf[(i + 399) % 100]) + i;
            if ((this.randBuf[i] % 2) == 1)
            {
                this.randBuf[i] = (this.randBuf[i + 1] << 21) ^ (this.randBuf[i + 1] * (this.randBuf[i + 1] & 30));
            }
        }
    }

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

    /// <summary>
    /// Retrieves a value from the random number array.
    /// </summary>
    /// <returns>A randomly generated unsigned integer</returns>
    private uint Random()
    {
        if (this.index == 0)
        {
            this.Roll();
        }

        uint y = this.randBuf[this.index];
        y = y ^ (y >> 11);
        y = y ^ ((y << 7) + 3794);
        y = y ^ ((y << 15) + 815);
        y = y ^ (y >> 18);
        this.index = (this.index + 1) % 100;
        return y;
    }