c++random-seedperceptronuniform-distribution

# Why does std::rand always generate 0?

I'm implementing a single-layer perceptron and there is a problem with my `weight_coef` function such as it is generating 0 every time the function is called. Thus I get inaccurate results when calculating `activation`. Here is a snippet of my `weight_coef` function, which is supposed to generate a number between 0 and 1:

``````#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>

using namespace std;

//Helper function to generate a random number between 0 and 1
double weight_coef() {
//((double)rand() / RAND_MAX);
srand(time(NULL));
double random = static_cast<double>(rand() / RAND_MAX);
random = round(random * 100) / 100.0; //to 2 dec points
return random;
}

int main() {
// Set up the variables
vector<double> w = { weight_coef(), weight_coef(), weight_coef()};
}
``````

Would be grateful if you could suggest what's wrong.

Solution

• The problem is that `std::rand` returns an integer that is guaranteed to be between 0 and `RAND_MAX`. Thus the weight coefficient code

``````double weight_coef() {
srand(time(NULL));
double random = static_cast<double>(rand() / RAND_MAX); // <-- LOOK
/* The above line will always set random to 0 */
random = round(random * 100) / 100.0;
return random;
}
``````

will always return 0 (actually it will almost always be 0, and will be be 1 with probability `1/RAND_MAX`). One solution would be to take the random integer, mod it by 100, and then interpret that as your two decimal digit probability. But note that this will be slightly nonuniform, as `RAND_MAX` is probably not divisible by 100 (and is likely 2^31 - 1 = 2147483647).

If you want to make a uniform random variable, you can do something like

``````#include <iostream>
#include <random>

const int LOWER_BOUND = 0;
const int UPPER_BOUND = 100;

std::random_device rand_dev;
std::mt19937 gen;
std::uniform_int_distribution<int> dist;

int random_int() {
return dist(gen);
}

int main()
{
gen = std::mt19937(rand_dev());
dist = std::uniform_int_distribution<int>(LOWER_BOUND, UPPER_BOUND);

for (int i = 0; i < 10; i++) {
std::cout << random_int() << "\n";   // generate 10 random integers
}
}
``````

I note it is also not a good idea to repeatedly reinitialize the seed on every function call. Instead, set the seed once - possibly in main (as done implicitly in the code snippet I posted).