简体   繁体   中英

Different behavior between same call for pseudo-random number generator

I'm currently working on implementing a simple graph class and one of the methods I want for it is for it to return a random neighbor, algorithm shown below. However, I found out that everytime I ran the program, the return nborList[r] always returned the same element in the nborList.

IDType Graph::random_neighbor(const IDType source) const
{
   IDVector nborList = neighbors(source);
   IDType r = nrand(nborList.size());

    cout << "TEST Neighbors: ";
    for (IDVector::const_iterator iter = nborList.begin();
        iter != nborList.end(); ++iter)
        cout << *iter << " ";
    cout << endl;
    cout << "TEST Rand: " << r << endl;

   return nborList[r];
}

int nrand(int n) // Returns number [0, n), taken from Accelerated C++
{
    if (n <= 0 || n > RAND_MAX)
        throw domain_error("Argument to nrand is out of range");

    const int bucket_size = RAND_MAX / n;
    int r;

    do r = rand() / bucket_size;
    while (r >= n);

    return r;
}

The test.cpp file that I'm using this Graph class in has this code:

#include <ctime>
#include <iostream>
#include "Graph.h"

using std::cout;
using std::endl;

int main()
{
    srand(time(NULL));

    Graph G(50);
    for (int i = 1; i < 25; ++i)
        if (i % 2 == 0)
            G.add_edge(0, i);
    G.add_edge(2, 49);

    cout << "Number of nodes: " << G.size() << endl;
    cout << "Number of edges: " << G.number_of_edges() << endl;
    cout << "Neighbors of node 0: ";
    IDVector nborList = G.neighbors(0);
    for (IDVector::const_iterator iter = nborList.begin();
        iter != nborList.end(); ++iter)
        cout << *iter << " ";

    cout << endl << endl;
    cout << "Random neighbor: " << G.random_neighbor(0) << endl;
    cout << "Random number: " << nrand(nborList.size()) << endl;
    return 0;
}

Output:

Number of nodes: 50
Number of edges: 13
Neighbors of node 0: 2 4 6 8 10 12 14 16 18 20 22 24 

TEST Neighbors: 2 4 6 8 10 12 14 16 18 20 22 24 
TEST Rand: 1
Random neighbor: 4
Random number: 9

The output I get is this, every time, except the last line that says Random number: 9 changes as it should. However, the TEST Rand: 1 is always 1, sometimes when I recompile it'll change to a different number, but upon multiple runs it stays the same number. The calls appear to be the same in both places, using nrand(nborList.size()) where nborList = neighbors(source) .. help?

Thanks!

rand() is well known to be shonky. If you run some tests and use seeds which are close in time, the first number it produces will always be close in value. I'd suggest using something like boost::random if you can.

instead of the nrand function, why don't you just write

IDType r = rand() % nborList.size();

this will give you a number [0, n] where n is nborList.size() - 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM