rand() with srand() is giving strangely similar results. The return from rand() is very similar

﹥>﹥吖頭↗ 提交于 2020-01-15 07:51:07

问题


This is a seemingly common question, so I hope I don't sound redundant. But the range returned from rand() should be between 0 and RAND_MAX, however, when I do a very simple rand statement, I'm always getting returns within a very small range.

This range is something like 1,4XX,XXX,XXX. I figured this might be a clock thing, so I waited thirty minutes and I'm still getting numbers in the same range.

Here is some sample output from twenty minutes ago:

Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439810968
80
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439827775
29
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439827775
29
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439844582
78
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439878196
29
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439895003
78

and here is sample output from just now:

Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1456483512
78
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1456500319
80
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1456500319
80
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1456517126
29
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1456533933
78

I know rand() isn't perfect, but this seems too similar to be correct. If the range is 0 - RAND_MAX, it seems weird that every number returned is in the same range.

Here is the code I was testing:

#include <iostream>
#include <stdio.h>      /* printf, scanf, puts, NULL */
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */

int main(int argc, char const *argv[])
{
    /* declarations */
    srand(time(NULL));

    std::cout << std::rand() << std::endl;
    std::cout << std::rand()%100 << std::endl;
    return 0;
}

I don't think I needed all those #include statements, but I saw other people using them so I included them just in case it would affect my output, but it didn't.

Edit

So the links provided by @Mgetz and @Curious were super helpful. To consolidate,

Info page: http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution

Super helpful lecture (for real, watch this): https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful

I summarized what I heard in the lecture on my own notes, just so I won't have to re-research this another time if I forget. I didn't write the code here, most of the code is within on that "Info page" linked above. Most of the comments contain information from the lecture, though it isn't verbatim from the lecture. Again, I really recommend watching that. It is dense with good information.

#include <iostream>
#include <random>

int main(int argc, char const *argv[])
{
    /* https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful */

    /* Randomness Verson 1 : Deterministic */
    std::mt19937 mt(1234);
    std::uniform_int_distribution<int> dist(0,127);
    /* Default is int, but we could specify others.
     * The range is [inclusive, inclusive]
     * 
     * Above is Mersenne Twister RNG. It is deterministic, meaning we can get the same result
     * if we use "std::mt19937 mt(1234)"; or something like that. This could be useful for some
     * people (He mentions games, some experiments, et cetera). It is stupid fast.
     * 
     * However, it isn't cryptographically secure, but it pretty random as random goes. If you
     * track the output though, you could guess the next numbers, so don't use it for anything
     * secure.
     */

    /* Randomness Verson 2 */
    std::random_device rd;  //Will be used to obtain a seed for the random number engine
    std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
    std::uniform_int_distribution<int> dis(0, 127); // Inclusive
    /* This is not reproducible. This is not deterministic.
     * "Possibly Crypto-secure." Seems like using Random Device makes this near perfect random,
     * assuming some conditions. I'm not a man who's written security software, and if you are 
     * writing security software, I assume you're not looking at StackOverflow to figure out how
     * to do random numbers. The way he talked about it in the lecture made this seem much more 
     * secure, but I'm not sure what I'm talking about when it comes to these things
     */

    for (int i = 0; i < 3; ++i)
    {
        /* Below would output the pure Mersenne Twister output, deterministic. This seems to
         * be pretty random, but it isn't totally random. */
        std::cout << dist(mt) << " ";

        /* And below would output the random device output. This should be slower, but
         * more truly random. */

        //Use dis to transform the random unsigned int generated by gen into an int in [1, 6]
        std::cout << dis(gen) << " ";

        std::cout<< std::endl;
    }
}

回答1:


Using the modulus operator brings in some amount of bias in the resulting "random number". Further the working of the rand() function is implementation defined and does not follow a standard algorithm across platforms.

Consider using more modern C++11 random number generation features that use standard widely accepted random number generation algorithms, that work the same across platforms (given the same seed of course).

See the following example from the cppreference page for std::uniform_int_distribution

#include <random>
#include <iostream>

int main()
{
    std::random_device rd;  //Will be used to obtain a seed for the random number engine
    std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
    std::uniform_int_distribution<> dis(1, 6);

    for (int n=0; n<10; ++n)
        //Use dis to transform the random unsigned int generated by gen into an int in [1, 6]
        std::cout << dis(gen) << ' ';
    std::cout << '\n';
}

Here is link to a great talk by Stephan Levavej that goes into this more in depth https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful



来源:https://stackoverflow.com/questions/45066246/rand-with-srand-is-giving-strangely-similar-results-the-return-from-rand

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!