0

I don't get why it outputs the same number every time even though it should output a different number each time. rand() % 10 + 1, should output a number between 1 to 10 randomly but my code just outputs the same exact 5 number each time.

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    int v1;
    for(v1=0; v1 < 10; v1++) {
        v1 = rand() % 10 + 1;
        cout << v1 << endl;
    }
    return 0;
}
GG Bro
  • 65
  • 9
  • 2
    To make `rand()` (a bad PRNG) working, you must give it a seed. – Ted Lyngmo Oct 26 '19 at 04:42
  • Umm, what is your goal, exactly? A random number each time? – Momoro Oct 26 '19 at 04:44
  • The source of your problem is unclear to me, but I can tell you that reusing the same variable to store a count and a random variable probably won't end well. –  Oct 26 '19 at 04:45
  • @Momoro yeah, i want a random number each time, but this code always outputs 2, 8 , 5 , 1 and 10. even though its supposedly random. – GG Bro Oct 26 '19 at 04:45
  • 5
    Read how [`rand()`](https://en.cppreference.com/w/cpp/numeric/random/rand) works (specifically the default-seed when none is set by user-code). And while you're at it, read about the modern C++ [``](https://en.cppreference.com/w/cpp/numeric/random) library, which is *far* preferable to `rand()` in literally every conceivable way. That said, any particular reason you're using `v1` as *both* your loop control *and* the holder of your "random" value ? How do you think that affects *the loop* ?? – WhozCraig Oct 26 '19 at 04:46
  • Yeah, you probably didn't [seed it](https://stackoverflow.com/questions/5620163/use-of-srand-in-c). –  Oct 26 '19 at 04:46
  • 1
    You need to seed it, like Chipster is saying. Without seeding, you WILL keep on receiving the same numbers. – Momoro Oct 26 '19 at 04:48
  • Instead, do the loop with v1(first), then create a v2(to store the next numbers.) – Momoro Oct 26 '19 at 04:50
  • 1
    Perhaps my link is close enough to a dupe. Also, perhaps someone with the rep could protect. There is also the option that one of us writes an answer. –  Oct 26 '19 at 04:53
  • Thank you guys for help, i've finally found out the reason why it outputs the same number. – GG Bro Oct 26 '19 at 04:53
  • @Chipster i just included the library and the function srand (time(NULL)); – GG Bro Oct 26 '19 at 04:58
  • 3
    @Chipster Don't stop there. I'm not even sure what the real *problem* is (not the code bugs, the actual problem this code is trying to solve). Obviously there's some seeding missing, but wth is up with reusing `v1` for both the rand-result *and* loop control? The question description indicates 5 numbers are sought, but absolutely nothing in the loop control to ensure that. I'm genuinely curious what this code is *really* supposed to be doing. – WhozCraig Oct 26 '19 at 04:58
  • @Chipster I was making a matchstick game initially and one of my task was that the program should randomly changed the difficulty every once in a while inside a while loop. – GG Bro Oct 26 '19 at 05:01
  • It runs fine on my compiler. The code is fine there must be some compiler issue. Try some other compiler. Or try this: [JDoodle C++ Compiler](https://www.jdoodle.com/online-compiler-c++/) – Murtaza Ahmad Oct 26 '19 at 04:45
  • @GGBro Do read WhozCraig's answer. It'll make future random events much more random. – Ted Lyngmo Oct 26 '19 at 05:44

2 Answers2

3

The intended goal of your code is sketchy at best, and your problem description isn't doing it any favors. The code itself could be taken a number of ways. I think you're trying to draw ten random numbers from a uniform distribution. The modern way to do that would be something like this:

Simple Uniform Distribution

#include <iostream>
#include <random>

int main()
{
    std::mt19937 prng{ std::random_device{}() };
    std::uniform_int_distribution<> dist(1, 10);

    for (int i = 0; i < 10; ++i)
        std::cout << dist(prng) << ' ';
    std::cout.put('\n');
}

Note the seeding of the mersenne-twister prng, std::mt19937, is done through the library interface to some source of entropy using std::random_device. That prng is then used to feed the non-trivial mechanics of a std::uniform_int_distribution, which is limited to the domain {1..10} inclusively. Note that this is not going to prevent duplicates. Some sample runs appear below (and it had better vary when you try it):

Output (varies)

7 8 3 4 4 5 8 5 5 3

Selection Without Replacement

If instead you're interested in drawing random selection without repetition there are a number of ways to do it, but the one I prefer for small domains like this is to simply sequence the numbers, random-shuffle them, then iterate to draw your random order. Again, we'll use a properly-seeded mersenne-twister prng, but this time we'll use it as the random source for a library-provided shuffle operation of a sequence we filled with our very-limited domain from which to draw:

#include <iostream>
#include <random>
#include <vector>
#include <numeric>
#include <algorithm>

int main()
{
    std::mt19937 rng{ std::random_device{}() };
    std::vector<int> vec(10);

    std::iota(vec.begin(), vec.end(), 1);
    std::shuffle(vec.begin(), vec.end(), rng);

    for (auto x : vec)
        std::cout << x << ' ';
    std::cout.put('\n');
}

Output (varies)

6 7 10 2 4 8 3 1 5 9

Notable functions used above:

  • std::iota is a simple ascending numeric sequence generation algorithm
  • std::shuffle is a random shuffle algorithm utilizing a RNG source you provide to perform the shuffle operation.

Your Code

Both of the methods above are preferable to what you seem to be trying to do. Bias introduced with modulo against rand() can be a real problem, and only you know for sure whether it will really matter. If you want to guard against it, use one of the methods I showed earlier (whichever is appropriate for your needs).

That said, your code is probably only missing a proper seeding. According to the library standard, any invoke of rand() prior to seeing with srand will behave as if srand(1) was used. That explains your repetitious results from run to run. Assuming your use of v1 as both a control loop variable and a datum holder from rand modulo calculation is a bug in its own, addressing both would look like this:

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

int main()
{
    std::srand(static_cast<unsigned>(std::time(nullptr)));

    for (int i = 0; i < 10; ++i)
        std::cout << 1 + std::rand() % 10 << ' ';
    std::cout.put('\n');
}

Output (varies)

9 1 10 6 8 7 5 9 4 10

That said, I caution against doing this. There are plenty of things you can make mistakes on, and the bias is always in the background just waiting to bite. Use one of the other methods as warranted

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • I just realized that I approached the topic of seeding many moons ago. If you don't mind me piggybacking: [What is the proper way of seeding std::mt19937 with std::chrono::high_resolution_clock inside a class?](https://stackoverflow.com/questions/56242943/what-is-the-proper-way-of-seeding-stdmt19937-with-stdchronohigh-resolution/56266117#56266117) Please remove it if you don't approve. – Ted Lyngmo Oct 26 '19 at 05:59
  • @WhozCraig Thanks for your input, I'm still new with c++ and coding in general so i particularly don't know the do's and don'ts since there many ways to tackle a single problem. There's also too much library that i don't know of currently so i'm limited at the ones that i know and the ones that i find easier to understand. But i'll read through this and try to understand the difference. – GG Bro Oct 26 '19 at 06:25
2

You need to use this

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

using namespace std;
int main()
{
    srand(time(nullptr));
    int v1;
    for(v1=0; v1 < 10; v1++) {
        v1 = rand() % 10 + 1;
        cout << v1 << endl;
    }
    return 0;
}