1

I want to generate random numbers that deppend on input from user.

For example if user inputs 8, I want to generate number from 5 to 7, (8 - 3) to (8 - 1)

My code:

#include <iostream>
#include <time.h>

int main()
{

    int x1;
    int x2;

    std::srand(time(0));

    while (true)
    {
        std::cout << "input : ";
        std::cin >> x1;

        x2 = std::rand() % (x1 - 1) + (x1 - 3);

        std::cout << "result : ";
        std::cout << x2 << std::endl;
    }
    return 0;
}

But the output is:

input : 8
result : 7
input : 8
result : 10
input : 8
result : 8

And I want result to be from 5 to 7.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • Using more modern methods, you can use a [uniform int distribution](https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution). For your current solution, try to work out on pencil and paper how you'd use modulo and addition to constrain a random value to between `lowerBound` and `upperBound`. Hint: Right now your lower bound is `x1 - 3` and your upper bound is `2*x1 - 3`. – Nathan Pierson Mar 13 '21 at 22:03

2 Answers2

0

Addressing your problem

With the expression:

x2 = std::rand() % (x1 - 1) + (x1 - 3); 

Using your sample input, rand % (x1 - 1) will be rand % 7, this will render you values from 0 to 6, adding 5 to that you'll have values from 5 to 11.

If you are adamant in using rand you can use something like this:

x2 = rand() / (RAND_MAX / ((x1 - 1) - (x1 - 3) + 1) + 1) + x1 - 3;

Live sample

The interval is corrected, and this is a less biased method of obtaining the random value than using the modulo, though this problem is never completely solvable when using rand, it's a known drawback, there are others, you can find several threads in the website which provide solid reasoning as to why you shouldn't use it, like, for instance:

Why is the use of rand() considered bad?

Why do people say there is modulo bias when using a random number generator?

You also have this more technical document kindly provided by njuffa:

Fast Random Integer Generation in an Interval

Among many others.


Recommend method

C++ <random> header provides better random number generation facilities, for example using std::random_device and the Mersenne twister engine:

#include <iostream>
#include <random>

int main()
{
    int x1;
    int x2;

    std::random_device rand_d; // random number from hardware
    std::mt19937 generator(rand_d()); // seed
    
    while (true)
    {
        std::cin >> x1;
        std::uniform_int_distribution<> uniform_value(x1 - 3, x1 - 1); // setup the range
        x2 = uniform_value(generator); // generante the value
        std::cout << "result : " << x2 << "\n";
    }
}

Live sample

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • 1
    Not my DV, but there might be objections to teaching the use of the modulo operator for restricting the output of a source of uniformly distributed random numbers to a specific integer range. This has well-known draw-backs. State of the art in this regard is represented by: Daniel Lemire, "Fast random integer generation in an interval." *ACM Transactions on Modeling and Computer Simulation*, Vol. 29, No. 1, pp.1-12. ([preprint online](https://arxiv.org/pdf/1805.10941)) – njuffa Mar 14 '21 at 10:25
  • @njuffa, yep, it can be that, I just went along with the OP method and a should have provided a more solid solution, added that, better late than never I guess, thanks for the feedback. – anastaciu Mar 14 '21 at 11:08
  • That business with `RAND_MAX` gains you nothing over a simple `rand() % 3`. Whatever you do, the outcome will necessarily be ever so slightly biased, because the number of possible values for `rand()` is not (usually) a multiple of 3. – TonyK Mar 14 '21 at 11:14
  • @TonyK, granted, but the fault is the same, using `rand` when we can use far better methods. – anastaciu Mar 14 '21 at 11:18
-3
x2 = std::rand() % 3 + (x1 - 3);
TonyK
  • 16,761
  • 4
  • 37
  • 72