4

I need help figuring out how to generate a set amount of random numbers between two user-inputted values, inclusively. Just so you know, I have searched for this but am not finding what I have just stated. Here is my code:

#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

int main()
{
    int userBeg, userEnd, outPut;

    cout << "Enter a start value: ";
    cin >> userBeg;
    cout << "Enter an end value: ";
    cin >> userEnd;

    srand(time(NULL)); //generates random seed val

    for (int i = 0; i < 5; i++) {
      //prints number between user input, inclusive
    outPut = rand()%((userEnd - userBeg) + 1); 
    cout << outPut << "  ";
    }//end for

    return 0;
}//end main 

I'm confused with the output I get for the following ranges: 1-100 yield output numbers which fall in-between, but not including, the boundaries such as 50, 97, 24, 59, 22. But, 10-20 yield numbers such as 1, 14, 6, 12, 13. Here, the output is outside of the boundaries as well as in-between them. What am I doing wrong?

Thank you in advance for your help!

bluthunder
  • 57
  • 1
  • 1
  • 6
  • `outPut +=userBeg` – Danh Oct 27 '16 at 03:26
  • 1
    If you are using C++11, take a look at [`std::uniform_int_distribution`](http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution) – Danh Oct 27 '16 at 03:28
  • If `rand` is fast but low quality, then you can (probably) get better randomness by dividing its result by some suitable small constant, to remove the (influence of) the last few bits, before taking your bite of bits. – Cheers and hth. - Alf Oct 27 '16 at 03:58

4 Answers4

11

Using the c++11 random library.

You could use std::default_random_engine (or any other random engine) with std::uniform_int_distribution.

The values you pass to std::uniform_int_distribution will be the lower and upper bounds of your random range.

e.g.

#include <iostream>
#include <random>

int main()
{
    const int nrolls = 100;

    std::default_random_engine generator;
    std::uniform_int_distribution<int> distribution(0,9);

    int p[nrolls]={};

    for (int i=0; i<nrolls; ++i)
    {
        p[i] = distribution(generator);
    }

    std::cout << "uniform_int_distribution (0,9):" << '\n';
    for (int i=0; i<nrolls; ++i)
    {
        std::cout << i << ": " << p[i] << '\n';
    }
}

If you wish to seed the random engine, create it like.

unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();

std::default_random_engine generator(seed);
Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
6

rand returns number between 0 and RAND_MAX. By taking modulo userEnd - userBeg + 1 the boundaries will be limited to 0 and userEnd - userBeg. If the random number should be within given boundaries, then userBeg should be added, so the calculus becomes

    outPut = rand()%((userEnd - userBeg) + 1) + userBeg; 
karastojko
  • 1,156
  • 9
  • 14
  • 1
    This answer will produce biased results, some numbers will be more likely than others. Better to use the more modern random number facilities of C++ rather than `rand`. – Mark Ransom Oct 27 '16 at 04:16
  • 2
    The question was regarding boundaries, not `rand` accuracy. – karastojko Oct 27 '16 at 04:20
  • 2
    This method *reduces* the randomness even if `rand` is perfect. It might suffice for non-critical applications, but everybody should be aware of the caveat. – Mark Ransom Oct 27 '16 at 04:24
4

It's still experimental, but it is exactly what you want

http://en.cppreference.com/w/cpp/experimental/randint

#include <iostream>
#include <experimental/random>

int main()
{
    int random_number = std::experimental::randint(100, 999);
    std::cout << "random 3-digit number: " << random_number << '\n';
}

Edited: it's really random http://en.cppreference.com/w/cpp/numeric/random

khôi nguyễn
  • 626
  • 6
  • 15
  • 1
    I'd eliminate the `experimental` part of this answer, there's a standard solution available since 2011: http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution – Mark Ransom Oct 27 '16 at 04:14
  • Yes, I've already known it. I just want to give another short approach for the question. Btw, thanks. – khôi nguyễn Oct 27 '16 at 05:28
2

For the rand to work you need to do:

#include <cstdlib>

int main() {

    int Min = 103;
    int Max = 113;

    int Number = std::rand() % (Max + 1 - Min) + Min;

    return 0;
}

I omitted the cin for clarity. (Max + 1 - Min) makes it inclusive. + Min sets the minimum value!

So stuffed into a function you may use:

int randint(int Min, int Max) {
    return std::rand() % (Max + 1 - Min) + Min;
}

After testing it works with negative numbers as well as positive.

Sample outputs (with a loop and cout):

11-23

The number is: 13
The number is: 18
The number is: 14
The number is: 17
The number is: 18
The number is: 18
The number is: 23
The number is: 15
The number is: 11
The number is: 22
The number is: 22
The number is: 11
The number is: 22
The number is: 16
The number is: 14
The number is: 21
The number is: 16
The number is: 19
The number is: 15
The number is: 13
The number is: 17

1239-1242

The number is: 1240
The number is: 1242
The number is: 1239
The number is: 1241
The number is: 1241
The number is: 1241
The number is: 1239
The number is: 1240
The number is: 1240
The number is: 1240
The number is: 1242
The number is: 1240
The number is: 1242
Community
  • 1
  • 1
Carl
  • 2,057
  • 1
  • 15
  • 20
  • std::rand() is in cstdlib not random http://en.cppreference.com/w/cpp/numeric/random/rand – khôi nguyễn Oct 27 '16 at 03:35
  • Hmm... Actually compiles and runs just fine without any includes – Carl Oct 27 '16 at 03:37
  • 1
    Of course, then you shouldn't include library that isn't used. – khôi nguyễn Oct 27 '16 at 03:42
  • I have already updated the answer. Thanks for pointing that out! :D – Carl Oct 27 '16 at 03:42
  • std::rand make me some trouble, on ideone.com, if I use C++14 then it just fine, but for G++ 5.1 and G++4.3.2 I must include cstdlib. – khôi nguyễn Oct 27 '16 at 03:48
  • 1
    Find it out :) http://stackoverflow.com/questions/35910043/why-does-rand-compile-without-including-cstdlib-or-using-namespace-std Since you use C++11 – khôi nguyễn Oct 27 '16 at 03:52
  • Well that explains. Turns out I had included iostream when testing the code! I have updated the answer to include the cstdlib header to avoid compiler errors if anyone should just copy paste it. Thanks for the link! – Carl Oct 27 '16 at 03:55
  • @Carl F. Thanks for your answer! In your output, however, the random numbers generated include the boundaries. How would I go about writing my code if I didn't want to include my boundaries? – bluthunder Oct 27 '16 at 04:04
  • You would simply `std::rand() % (Max - Min - 1) + (Min + 1);` shuffle the plus and minus 1's a little. Keep in mind though that this it is not optimal to have both ends be non-inclusive as a random between the value 1 and 1 will always yield 2 for example. – Carl Oct 27 '16 at 04:13
  • Thanks! My prof requires that the output does not include the boundaries. In the case of the same max/min values, I'll add an if statement to check and notify the user they can't equal. – bluthunder Oct 27 '16 at 04:24