user2417339
user2417339

Reputation:

Why is rand giving me almost identical (but slightly different) numbers each time

I wrote the following piece of code to generate random numbers in c++

#include <stdlib.h>
#include <iostream>
#include <ctime>

#define ARRAY_SIZE 5
#define MAX_VAL ARRAY_SIZE*5+1

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

  int arr [ARRAY_SIZE];
  for (int i = 0; i < ARRAY_SIZE; i++) {
    arr[i] = (rand() % MAX_VAL);
  }

  for (int i = 0; i < ARRAY_SIZE; i++) {
    printf ("%d\n", arr[i]);
  }

  return 0;
}

When I run this I get almost identical numbers each time:

tyler@Tylers-MacBook-Pro hw2 % ./MergeSort
11
16
16
21
16
tyler@Tylers-MacBook-Pro hw2 % ./MergeSort
21
11
21
11
6
tyler@Tylers-MacBook-Pro hw2 % ./MergeSort
6
6
1
16
6
tyler@Tylers-MacBook-Pro hw2 % ./MergeSort
16
1
16
6
21
tyler@Tylers-MacBook-Pro hw2 % ./MergeSort
1
21
21
11
21
tyler@Tylers-MacBook-Pro hw2 % ./MergeSort
1
21
21
11
21
tyler@Tylers-MacBook-Pro hw2 % ./MergeSort
11
16
1
1
11
tyler@Tylers-MacBook-Pro hw2 % ./MergeSort
11
16
1
1
11
tyler@Tylers-MacBook-Pro hw2 % ./MergeSort
21
1
6
6
1

Why is my random number generator only giving me the values: 1, 6, 11, 16 and 21? This makes no sense to me. I made sure to seed it and the numbers aren't always in the same order which is what makes this even more confusing. As a side note I am using OSX.

Upvotes: 0

Views: 103

Answers (3)

Travis Gockel
Travis Gockel

Reputation: 27633

The problem is that MAX_VAL is defined as ARRAY_SIZE*5+1, not (ARRAY_SIZE*5+1). This means that your use in arr[i] = (rand() % MAX_VAL); expands to:

arr[i] = (rand() % 5 * 5 + 1);

There aren't a lot of options (only 5 possibilities), which is why you're seeing the same numbers. You can fix this by parenthesizing the definition of MAX_VAL or making it a contant variable:

const unsigned int MAX_VAL = ARRAY_SIZE * 5 + 1;

A secondary issue is the use of srand(time(NULL)). On most systems, time will return the same value if the program is run in the same second. This means running the program in rapid succession (within the same second) will yield the same results. It is preferable to use the PRNG facilities in <random>.

Upvotes: 6

tadman
tadman

Reputation: 211560

Others have pointed out the two primary issues in this code, but it's worth showing the C++ way of doing things here for contrast and to un-learn a lot of the C thinking that broke this code in the first place.

The C++ version of this code side-steps a lot of the problems here by using facilities C++ has and C lacks:

#include <random>
#include <vector>
#include <iostream>

int main() {
  // Define constants instead of using #define, as this avoids interpolation syntax issues
  const size_t array_size = 5;
  const int max = array_size * 5 + 1;

  // Use the C++ random number generator facilities
  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_int_distribution<> dis(0, max);

  // Use a dynamically sized array
  std::vector<int> arr;

  for (int i = 0; i < array_size; ++i) {
    arr.push_back(dis(gen));
  }

  // Use C++ container iteration to simplify code
  for (const int& i : arr) {
    // Use streams for output
    std::cout << i << std::endl;
  }

  return 0;
}

Upvotes: 1

OdedR
OdedR

Reputation: 123

This is because of your using of #define MAX_VAL

The actual calculation is rand() % 5 * 5 + 1, which means, you first modulo the rand() result with 5, and then multiple by 5, and then add 1.

I assuming you mean to write rand () % (5 * 5 + 1) That can be resolved by:

#define MAX_VAL (ARRAY_SIZE * 5 + 1)

Upvotes: 0

Related Questions