Programing

Linux에서는 동일한 번호를 생성하지만 Windows에서는 생성하지 않습니다.

lottogame 2020. 9. 9. 18:55
반응형

Linux에서는 동일한 번호를 생성하지만 Windows에서는 생성하지 않습니다.


아래 코드는 간격 [1,100]에서 5 개의 의사 난수 목록을 생성하기위한 것입니다. 나는 시스템 시간을 유닉스 시간으로 반환 하는 default_random_enginewith를 시드합니다 . Microsoft Visual Studio 2013을 사용하여 Windows 7에서이 프로그램을 컴파일하고 실행하면 예상대로 작동합니다 (아래 참조). 그러나 g ++ 컴파일러로 Arch Linux에서 그렇게하면 이상하게 작동합니다.time(0)

Linux에서는 매번 5 개의 숫자가 생성됩니다. 마지막 4 개의 숫자는 각 실행마다 다르지만 (종종 그렇듯이) 첫 번째 숫자는 동일하게 유지됩니다.

Windows 및 Linux에서 5 개 실행의 출력 예 :

      | Windows:       | Linux:        
---------------------------------------
Run 1 | 54,01,91,73,68 | 25,38,40,42,21
Run 2 | 46,24,16,93,82 | 25,78,66,80,81
Run 3 | 86,36,33,63,05 | 25,17,93,17,40
Run 4 | 75,79,66,23,84 | 25,70,95,01,54
Run 5 | 64,36,32,44,85 | 25,09,22,38,13

수수께끼에 덧붙여, 그 첫 번째 숫자는 Linux에서 주기적으로 1 씩 증가합니다. 위의 출력을 얻은 후 30 분 정도 기다렸다가 다시 1 번째 숫자가 변경되어 현재는 항상 26으로 생성되고 있음을 확인했습니다. 주기적으로 1 씩 계속 증가했으며 현재는 32입니다. 값이 time(0).

첫 번째 숫자가 실행 중에 거의 변경되지 않고 변경되면 1 씩 증가하는 이유는 무엇입니까?

코드. 5 개의 숫자와 시스템 시간을 깔끔하게 인쇄합니다.

#include <iostream>
#include <random>
#include <time.h>

using namespace std;

int main()
{
    const int upper_bound = 100;
    const int lower_bound = 1;

    time_t system_time = time(0);    

    default_random_engine e(system_time);
    uniform_int_distribution<int> u(lower_bound, upper_bound);

    cout << '#' << '\t' << "system time" << endl
         << "-------------------" << endl;

    for (int counter = 1; counter <= 5; counter++)
    {
        int secret = u(e);
        cout << secret << '\t' << system_time << endl;
    }   

    system("pause");
    return 0;
}

무슨 일이 일어나고 있는지 :

  • default_random_enginelibstdc ++ (GCC의 표준 라이브러리) minstd_rand0에서는 간단한 선형 합동 엔진입니다.

    typedef linear_congruential_engine<uint_fast32_t, 16807, 0, 2147483647> minstd_rand0;
    
  • 이 엔진이 난수를 생성하는 방법은 x i + 1 = (16807x i + 0) mod 2147483647입니다.

  • Therefore, if the seeds are different by 1, then most of the time the first generated number will differ by 16807.

  • The range of this generator is [1, 2147483646]. The way libstdc++'s uniform_int_distribution maps it to an integer in the range [1, 100] is essentially this: generate a number n. If the number is not greater than 2147483600, then return (n - 1) / 21474836 + 1; otherwise, try again with a new number.

    It should be easy to see that in the vast majority of cases, two ns that differ by only 16807 will yield the same number in [1, 100] under this procedure. In fact, one would expect the generated number to increase by one about every 21474836 / 16807 = 1278 seconds or 21.3 minutes, which agrees pretty well with your observations.

MSVC's default_random_engine is mt19937, which doesn't have this problem.


The std::default_random_engine is implementation defined. Use std::mt19937 or std::mt19937_64 instead.

In addition std::time and the ctime functions are not very accurate, use the types defined in the <chrono> header instead:

#include <iostream>
#include <random>
#include <chrono>

int main()
{
    const int upper_bound = 100;
    const int lower_bound = 1;

    auto t = std::chrono::high_resolution_clock::now().time_since_epoch().count();

    std::mt19937 e;
    e.seed(static_cast<unsigned int>(t)); //Seed engine with timed value.
    std::uniform_int_distribution<int> u(lower_bound, upper_bound);

    std::cout << '#' << '\t' << "system time" << std::endl
    << "-------------------" << std::endl;

    for (int counter = 1; counter <= 5; counter++)
    {
        int secret = u(e);

        std::cout << secret << '\t' << t << std::endl;
    }   

    system("pause");
    return 0;
}

In Linux, the random function is not a random function in the probabilistic sense of the way, but a pseudo random number generator. It is salted with a seed, and based on that seed, the numbers that are produced are pseudo random and uniformly distributed. The Linux way has the advantage that in the design of certain experiments using information from populations, that the repeat of the experiment with known tweaking of input information can be measured. When the final program is ready for real-life testing, the salt (seed), can be created by asking for the user to move the mouse, mix the mouse movement with some keystrokes and add in a dash of microsecond counts since the beginning of the last power on.

Windows random number seed is obtained from the collection of mouse, keyboard, network and time of day numbers. It is not repeatable. But this salt value may be reset to a known seed, if as mentioned above, one is involved in the design of an experiment.

Oh yes, Linux has two random number generators. One, the default is modulo 32bits, and the other is modulo 64bits. Your choice depends on the accuracy needs and amount of compute time you wish to consume for your testing or actual use.

참고URL : https://stackoverflow.com/questions/32730906/random-generates-same-number-in-linux-but-not-in-windows

반응형