0

I'm studying arrays and can't figure out what I'm doing wrong.

I need to output an array with 8 random generated numbers between 5 and 25.

Before down voting my question : /, I tried looking already for similar questions on stackoverflow but most of them contain the use of algorithm's or different kinds of sort-techniques. I cannot use those technique's in my answer. It 'should' be easier to solve this.

Where is the problem in my code and why doesn't my random number generate a new number while i'm looping trough the array?

int table[8];
int random_number= rand() % 25 + 5;

for (int i=0; i<8; i++)
{
    table[i] = random_number;
    cout << table[i] << " ";
}

As I compile and run it, it gives me 8 times the same number, however I'm letting my array loop through each single index, while putting a random number in it? On paper this should work normally, right?

Is there anyone who can explain what I did wrong and why my loop is not working correctly?

nbro
  • 15,395
  • 32
  • 113
  • 196
Kahn Kah
  • 1,389
  • 7
  • 24
  • 49
  • 4
    `random_number` changes when you tell it to change, which you only did when initializing it. You're also reinventing `std::generate`. – chris Aug 18 '14 at 02:37
  • 3
    You only call `rand()` once, which generates a random value. You store that value in a variable, and assign the same value to all elements. The fact that this value is named `random_number` doesn't magically make it change its value every time it's accessed. To get 8 different numbers, move `rand()` call into the loop. – Igor Tandetnik Aug 18 '14 at 02:37
  • 2
    If you want the numbers to be between 5 and 25, you need to use `int random_number= rand() % 21 + 5;` – R Sahu Aug 18 '14 at 02:40
  • Wow! I wasn't aware that you could do this! table[i]=random_number=rand() % 25 + 5; actually worked! Thank you very much Igor! – Kahn Kah Aug 18 '14 at 02:40
  • Read about [`std::vector`](http://en.cppreference.com/w/cpp/container/vector) or [`std::array`](http://en.cppreference.com/w/cpp/container/array) and [`std::generate`](http://en.cppreference.com/w/cpp/algorithm/generate) and the C++ [pseudo-random functions and classes](http://en.cppreference.com/w/cpp/numeric/random). – Some programmer dude Aug 18 '14 at 02:42
  • rand() % 25 + 5 won't work. Because it can give you value more than 25. The solution RSahu mentioned is what you need. – Tahlil Aug 18 '14 at 03:12
  • Modulo based solutions will in general produce biased distributions. – pjs Aug 18 '14 at 13:33
  • Where on earth did you get the idea that `table[i] = random_number;` would cause the initializing expression `rand() % 25 + 5` to run again for each loop iteration? The initializing expression runs _once_, _when the variable is initialized_. Then in each loop iteration that _one_ value of `random_number` is used _without any further modification_. – bames53 Aug 28 '14 at 16:36

5 Answers5

4

In c++11, with random facilities you may do

std::default_random_engine engine; // or other engine as std::mt19937
int table[8];
std::uniform_int_distribution<int> distr(5, 25);

std::generate(std::begin(table), std::end(table), [&](){ return distr(engine); });

Live example

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Or use std::bind as in auto rng = std::bind(distr, engine); std::generate(std::begin(table), std::end(table), rng); – user515430 Aug 26 '14 at 20:51
3

Generating random numbers in a range in C++ is not so trivial, as I know. In my example, you need to have a srand() and rand() function.

#include <iostream>
#include <cstdlib>//srand and rand
#include <ctime>//time

int main()
{
    /*

    [$] srand() gives to the rand() function a new "seed", which is a starting point
    (usually random numbers are calculated by taking the previous number (or the seed))

    You could also pass another different seed from time(0), for example:
            srand(3); 
    Numbers would be generated according to the seed 3, hence numbers would be the same every time

    [#] So how can we do the opposite?

    [$] That's why we need time(0)

    [#] So what exactly is time(0)?

    [$] time(0) returns the number of seconds since the UNIX epoch.

    [#] Why is this useful?

    [$] Because every time you make your program start, the number of second will be different (because the time passes)
    and therefore also the seed and, consequently, the random numbers generated will be different every time
    unless you start the program at the same time every time, which is improbable.

    [#] Ok, thank you :)

    */

    srand(time(0));


    int _min = 5;//min
    int _max = 25;//max

    const int total_numbers = 8;//total numbers you want to generate
    int _array[total_numbers] = {0};

    int random_number = -1;

    for(int i=0; i<total_numbers; ++i)
    {
        /*
        [$]
        This formula it's not obvious to understand,
        and it's a general formula you can use to generate numbers in a range.

        rand() % NUMBER will generate a number between 0 and the NUMBER.

        In our example, we want to generate between 5 and 25.

        [#] So what is the NUMBER ?

        If you believe or not, it's ((_max - _min) + 1), which in our case is 21.

        With 21 as our NUMBER, we will have the maximum number to be 20 and the minimum number to be 0.

        If we add 5 to the random number generated, we will have the minimum number equals to 5
        and the maximum number equals to 25, agree?

        [#] Thank you, well explained :)
        */

        random_number = _min + rand() % ((_max - _min ) + 1);

        _array[i] = random_number;
    }

    //Enhanced for loop
    for(int i : _array)
        std::cout << "Random number "<< i << '\n';

    return 0;
}
nbro
  • 15,395
  • 32
  • 113
  • 196
  • `random_number = _min + rand() % ((_max - _min ) + 1);` Although I wouldn't have leading `_` myself. – Keith Aug 18 '14 at 02:48
  • -1: This answer does not directly address the OP's main problem (that he doesn't understand how variables and initialization works) and instead goes on about a secondary mistake. (also IMO it gets how to generate random numbers in a range wrong: you should use `` and `std::uniform_int_distribution<>(5,25)`. Using `rand()` and `%` is bad practice.) – bames53 Aug 28 '14 at 16:42
  • @bames53 Why is it a bad practice? Explain, just don't say `yes` to everything. – nbro Aug 28 '14 at 16:45
  • It's bad practice because 1) using `%` correctly with `rand()` generally produces code that's difficult to read (where 'doing so correctly' means not introducing bias), so 2) people usually op not to bother using it correctly, so as to make the code simpler (as you do here), and 3) because `rand()` is generally a poor quality source of randomness. Oh, and 4) `rand()` can introduce data races in multi-threaded programs. Using the `` library addresses all these problems. – bames53 Aug 28 '14 at 16:48
  • @bames53 Bias? Are you serious? `3) because rand() is generally a poor quality source of randomness.`, why? – nbro Aug 28 '14 at 16:51
  • @bames53 My answer tries to explain it the best way possible, in my opinion it deserves something better, but I am nobody to decide, do what you want! – nbro Aug 28 '14 at 16:52
  • Yes, I'm serious. `rand()` is generally implemented as a Linear congruential generator, and many implementations produce low-order bits (the ones you get when you use `%`) that are very regular. Using `` lets you control the characteristics of your generator to match you needs. – bames53 Aug 28 '14 at 17:16
  • Actually this is the best solution a found for generating random numbers in c. I am going to use this without fear :) – fabio Apr 22 '17 at 15:50
0

As I compile and run it, it gives me 8 times the same number, however I'm letting my array loop through each single index, while putting a random number in it? On paper this should work normally, right?

No.

Variables are like storage boxes. You can put values in and then later you can get the value you put in back out.

int random_number = rand() % 25 + 5;

This line computes a value by executing the expression rand() % 25 + 5 and puts that value into the variable random_number. For example, maybe it computes the value 20 puts that value in the variable. Whenever you retrieve the value from the variable you will get the last number that was put in.

table[i] = random_number;

This line takes the variable random_number and retrieves its value (say, 20) and assigns it to table[i]. The important bit is that it does not matter here how random_number got its value. You put a value in the box and you'll only get that value back.

If you want a variable's value to change then you have to change it:

int random_number = rand() % 25 + 5; // create variable and set its value

random_number = rand() % 25 + 5; // set the variable's value again
random_number = rand() % 25 + 5; // set the variable's value again
random_number = rand() % 25 + 5; // set the variable's value again

If you want an entity that runs code when evaluated then you want a function:

int random_number() {
  return rand() % 25 + 5;
}

After defining this function you can use random_number() to reevaluate the expression:

int random_number() {
  return rand() % 25 + 5;
}

int main() {
  int table[8];

  for (int i=0; i<8; i++)
  {
    table[i] = random_number();
    cout << table[i] << " ";
  }
}

Note the difference here: random_number() is a function call which re-runs that rand() % 25 + 5 expression, and not a variable. Variables are just storage for whatever data you last put in. Functions run code when you call them.

bames53
  • 86,085
  • 15
  • 179
  • 244
0

suppose you want to generate random numbers in the range [start, end]:

rand()%end; 

gives you random integer in [0, end).

So, first you generate random number in [0, (end-start)] and then add 'start' to this range to get the desired range as shown below.

[0+start, end-start+start] = [start, end]

rand()%(end-start+1) + start;

hope this helps!

-2
int table[8];

for (int i=0;i<8;i++)
{
   table[i]=rand() % 21 + 5;
   cout << table[i] << " ";
}
Tahlil
  • 2,680
  • 6
  • 43
  • 84
  • Using the modulus operator, %, introduces a bias. That may not matter to the OP. But it is not a good solution in my opinion. – user515430 Aug 26 '14 at 20:54
  • 1
    Go and watch the first 8 minutes of the video http://channel9.msdn.com/events/GoingNative/2013/rand-Considered-Harmful. Stephan explains it much better than I can. – user515430 Aug 28 '14 at 04:58