Rand() возвращает одинаковые или очень похожие выходные значения [дубликаты]

Вопрос С++ здесь, используя Code::Blocks. Я пытаюсь запустить этот код, чтобы проверить псевдослучайную функцию

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{
    int count = 0;
    while (count < 10){
        srand(time(NULL));
        cout << rand() << ' ';
        cout << (time( NULL )) << " \n";
        count++;
    }
    return 0;
}

Результатом этого является 10 равных строк. На самом деле это не проблема, так как начальное значение здесь такое же, поэтому результат должен быть таким же. Проблема в том, что если я снова запущу эту программу, она выдаст 10 очень похожих строк с небольшими изменениями не только в выводе time(), но и в выводе rand.

srand(time(NULL)) дает очень похожие ответы, которые в основном имеют одно и то же возвращаемое значение, только немного больше.

(Возвращение 9631 при первом запуске, а затем 9656 при втором).

Мой вопрос: это ожидаемое поведение? И как я могу получить более разные результаты, например, 38 при первом запуске и 671 при втором?


person Jim_Maru    schedule 21.12.2013    source источник
comment
Не могли бы вы быть более точным. Что вы ожидаете увидеть? Что ты видишь? Как это не соответствует вашим ожиданиям?   -  person David Heffernan    schedule 21.12.2013


Ответы (3)


Чтобы создать случайное число с почти одинаковым начальным числом (время), вы можете добавить статическую переменную, чтобы rand() вел себя по-разному даже с одним и тем же параметром; или вы можете изменить параметр, когда получите то же время. Например:

int t=0;
...
rand(t=(t*7)^time(NULL));
person SliceSort    schedule 21.12.2013
comment
Это на самом деле отличное решение! Я сделал это, и я мог получить 100 различных решений, используя одно и то же время (запустив эту программу один раз, при этом счетчик времени увеличился до 100). Запустив его снова, кажется, что предсказуемость решений также очень, очень низкая. Единственное, что я должен добавить, это то, что вызов функции, который мне нужно было изменить, был srand, а не rand. Но я понял, что вы имели в виду. Большое спасибо! - person Jim_Maru; 22.12.2013

Здесь много заблуждений... Ожидается, что разница между двумя близкими друг другу вызовами time(NULL) невелика. В конце концов, время движется только так быстро. Следующая проблема заключается в том, что rand() возвращает (псевдо)случайное значение (разного качества): Случайное в данном случае означает, что вы можете получить 33 несколько раз, пока это непредсказуемо. При этом rand() зависит от реализации, и вполне может быть, что ваша реализация использует что-то вроде LCG, который не генерирует хорошие однородные случайные значения. Единственное исправление для этого — переключение на другой ранг. Поскольку он помечен как C++, вы можете заглянуть в случайный заголовок C++11 и использовать что-то вроде их реализации Mersenne Twister, которая является хорошим генератором псевдослучайных чисел, который производит случайные числа с отличным качеством и равномерным распределением.

person JustSid    schedule 21.12.2013
comment
Я все это знаю. Все, что я хочу сказать, это то, что, зная значение, которое я получу при первом запуске программы, я могу ожидать, какое значение я получу, если закрою ее и запущу снова. Я даже могу рассчитать, сколько времени потребуется, чтобы это число достигло определенной точки, и тогда я всегда могу предсказать число, которое я получу от него. Это не дает мне ничего случайного. Даже ничего псевдослучайного. Если бы я просто напечатал Time(null), результат был бы пиратски таким же: постоянно увеличивающееся число, которое растет с определенной скоростью. - person Jim_Maru; 21.12.2013

Разница между различными исполнениями, по-видимому, будет небольшой разницей в изменении time. Результаты rand могут быть разными для разных сред выполнения C, но вот реализация rand из Visual Studio 10.

int __cdecl rand ()
{
    _ptiddata ptd = _getptd();

    return( ((ptd->_holdrand = ptd->_holdrand * 214013L
        + 2531011L) >> 16) & 0x7fff );
}

Где holdrand хранит семя для начала. Это линейный конгруэнтный генератор, который обычно не обеспечивает высокого качества случайности. Это также каждый раз выбрасывает много состояния, что не помогает.

person Steve    schedule 21.12.2013
comment
То есть в основном это означает, что способ работы rand на самом деле является линейной и предсказуемой функцией? Что ж, тогда я думаю, что единственный способ заставить его выглядеть так, будто он возвращает случайное значение, — это ограничить максимальное значение, которое я могу получить от него. Например, с помощью rand(time(0))%10 или % однозначного числа. Чем больший результат я пытаюсь получить, тем более похожими и предсказуемыми будут результаты. - person Jim_Maru; 22.12.2013