2015-08-25 3 views
2

Скажем, у меня есть этот цикл:Можно ли посеять рандомизатор более одного раза, если это делается так?

for (i=0; i < 100; i++) 
{ 
    srand(time(NULL)); 
    printf("%d\n", rand()); 
} 

Если моя машина достаточно быстро, он должен печатать столько же 100 раз.

Но если я изменить это так:

for (i=0; i < 100; i++) 
{ 
    srand(time(NULL) + rand()); 
    printf("%d\n", rand()); 
} 

Затем он должен напечатать 100 различных номеров. Мой вопрос: есть ли что-то неправильное в посеве рандомизатора? Как насчет эффективности? Значительно снижает эффективность?

Ответ на вопрос, если я запустил рандомизатор в функции main() один раз, достаточно ли для других функций (т. Е. Мне не нужно его снова сеять в другой функции, которая использует rand())?

EDIT

Существует причина, почему я, возможно, придется использовать этот способ (если, конечно, не лучший способ, который я не знаю). Скажем, у меня есть пользовательская библиотека с функцией, которая использует rand(). Но эта функция не знает, был ли рандомизатор посеян до или нет. В этом случае я положил srand(time(NULL) + rand()) в эту функцию, чтобы убедиться, что рандомизатор посеян, даже если он раньше не был посеян.

Пример:

int main() 
{ 
    int i; 

    srand(time(NULL)); // Seeded here, but the print_rand() function does not know it 

    for (i=0; i < 100; i++) 
    { 
     print_rand(); 
    } 

    return(0); 
} 


// Pretend this function is in a library 
void print_rand() 
{ 
    srand(time(NULL) + rand()); // No guarantee if seeding was done before, so doing it here 

    printf("%d\n", rand()); 
} 

РЕДАКТИРОВАТЬ 2

Я просто протестировали его с петель 1000000. Посев однажды взял 0.024s и посев каждый раз принимал 4.972s. Поэтому я думаю, что это значительно снижает производительность, если это большой цикл.

+4

В большинстве случаев применение рандомизатора должно быть достаточным. В противном случае вам следует искать другие (более специализированные) рандомизаторы. – Kninnug

+0

Если вы хотите что-то действительно случайное, вам не следует использовать 'rand()'/'srand()'. Вместо этого используйте Intel Secure Key (доступный на процессорах Intel с 2006 года). – ArtOfWarfare

+2

Вопрос _why_ вы хотели бы засеять его более одного раза. Это похоже на вопрос: «Мне нужен красный дом. Можно ли красить мой дом красным 100 раз, а не только один раз?» – Lundin

ответ

2

Как правило, неправильно наносить PRNG более одного раза. Это действительно не увеличивает безопасность ПСЧ и не делает его быстрее (возможно, медленнее!)

, PRNG просто нужно быть посеяны раз

И да, это достаточно, чтобы семя его в одном месте. Другая история была бы, если бы у вас было несколько экземпляров одного и того же prng, но это не тот случай, это C не C++ и rand() является статичным.

Это все о том, что вы хотите сделать со случайными данными ...

  • Crypto материал? забыть использовать rand(), srand() и time()
  • случайный код игра AI? это может быть нормально
2

Не делайте этого.

Семя это один раз.

srand(time(NULL) + rand()); будет вводить статистическое отклонение при повторном использовании.Интуитивно это происходит из-за двух эффектов: (i) srand(rand()) будет эффективно опускать каждое другое число, которое увеличит дисперсию, и (ii) srand(time(NULL)) представит дополнительную константу добавки, которая вызовет более частое обращение к модулю оператора в генераторе это должно быть. Вы можете даже поставить под угрозу периодичность генератора.

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

+1

Вы правы в предвзятости, но это только потому, что rand() - линейный конг. генератор. –

+0

Reseeding производит смещение, но нет смещения от добавления смещения к семени, пока вы делаете это только один раз. Посев PRNG выбирает точку входа в свой цикл, добавляя сдвиг, просто перемещая точку входа. Цикл произведенных чисел идентичен независимо от того, где вы поднимаетесь на борт, пока вы не перегружаетесь. – pjs

+0

@pjs: абсолютно правильный. Я неоднозначно. – Bathsheba

1

Возможно, вы хотите улучшить выход с rand.

  1. Ваш метод не будет делать этого. Поскольку ваш код, скорее всего, будет известен, каждый может видеть, что вы сделали, а затем ваш метод эквивалентен вызову srand только один раз.
  2. Даже не зная вашего кода, просто зная, что вы используете rand, номера, генерируемые на нем, будут в большинстве систем легко предсказуемы.

rand полезен только для очень простых ситуаций, когда что-то должно выглядеть случайным для человека. Как простая игра. И в таких ситуациях достаточно называть srand.

Если вы действительно хотите генерировать случайные (определенные как «непредсказуемые») цифры, вы не должны использовать rand или random. Затем вам нужно провести некоторое исследование для вашей операционной системы и изучить правильную библиотеку, которая генерирует случайные числа.

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