I want to generate random number in range from 0 to 5, but for example, in some cases I don't need number 3, I only need 0, 1, 2, 4, 5. How can I generate random number within range, but with option to exclude numbers I don't need.
Asked
Active
Viewed 1.4k times
4
-
So if you're excluding 3, should the rest of the numbers come up with uniform probability? You can't talk about random numbers without talking about the probability distribution. – Joseph Mansfield Feb 17 '13 at 09:46
-
Do you mind if I remove Qt tag? Thanks ;) – Leo Chapiro Feb 17 '13 at 09:54
-
Possibly a duplicate of http://stackoverflow.com/questions/6443176/how-can-i-generate-a-random-number-within-a-range-but-exclude-some?rq=1 but context is not yet clear. – Thomas Feb 17 '13 at 09:59
-
Is 0..5 and one number to exclude just an example and you are planning to use much bigger ranges. This is important because of scalability. When using 0..1000000000 and excluding half of the numbers, there will definetly be trickier – El Hocko Feb 17 '13 at 10:01
-
Discard and try again? – Mikhail Feb 17 '13 at 10:11
-
@duDE it's ok, remove Qt tag, I placed it since I need this in Qt application but this is totally c++ related. I need range from 0 to 5, and number 3 is just example, in couple cases I need to exclude 2 or 4 – Alen Feb 17 '13 at 11:36
6 Answers
5
Here is yet another solution using modern features of C++ 11.
#include <functional>
#include <iostream>
#include <ostream>
#include <random>
int main()
{
std::random_device rd;
unsigned long seed = rd();
std::cout << "seed " << seed << std::endl;
std::mt19937 engine(seed);
// Distribution {0, 1, 2, 4, 5}
std::discrete_distribution<> dist {{1, 1, 1, 0, 1, 1}};
auto rng = std::bind(dist, std::ref(engine));
const int n = 10;
for (int i = 0; i != n; ++i)
{
int x = rng();
std::cout << x << std::endl;
}
return 0;
}

user515430
- 3,341
- 2
- 17
- 13
2
Are the numbers you want to exclude known at compile time? Then a simple lookup table should do:
static int table[] = {0, 1, 2, 4, 5};
int index = rand() % (sizeof table / sizeof *table);
int number = table[index];
Of course, rand()
is a terrible pseudo random number generator, but that's a different topic.

fredoverflow
- 256,549
- 94
- 388
- 662
-
How can `rand` of itself be a terrible pseudo random number generator? Surely that depends on the implementation? – TonyK Feb 17 '13 at 10:58
-
I found this solution as best, but instead rand() I'm using qrand(). If there is any better function for random numbers please show me. – Alen Feb 17 '13 at 11:49
-
3@Alen C++11 adds a whole header full of random number generators: [`
`](http://en.cppreference.com/w/cpp/header/random) – rubenvb Feb 17 '13 at 13:55
0
Just throw away the 3 in a loop:
template <typename Rng>
int rand_no_three (Rng& rng)
{
std::uniform_int_distribution<> dist (0, 5);
int c;
do {
c = dist (rng);
} while (c == 3);
return c;
}
Example usage:
std::mt19937 rng;
int c = rand_no_three (rng);

Alexandre C.
- 55,948
- 11
- 128
- 197
0
Here's a way of doing this without a lookup table in case you have memory constraints.
int map_fun(int i)
{
switch(i)
{
case 3: return 4;
case 4: return 5;
}
return i;
}
int main()
{
int i= map_fun(random_between(0, 4));
}

nurettin
- 11,090
- 5
- 65
- 85
0
here's an example using the java-code from this post: How can I generate a random number within a range but exclude some? translated to c++.
This is a little bit more generic and no unnecessary loops are used.
I also made a distribution, range and occurance - check in this program:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <time.h>
#include <map>
using namespace std;
int getRandomWithExclusion(int start, int end, vector<int> &excludes){
unsigned int max = end - start + 1 - excludes.size();
int random = start+(rand() % max);
for (unsigned int i = 0;i<excludes.size();i++) {
int ex = excludes[i];
if (random < ex){
break;
}
random++;
}
return random;
}
int main()
{
srand (time(NULL));
vector<int> excl;
map<int,int> distMap;
excl.push_back(-2);
excl.push_back(3);
for(int i=0;i<100000;i++){
int val = getRandomWithExclusion(-5,5,excl);
if (distMap.find(val) == distMap.end()){
distMap[val]=0;
}
int key = distMap[val]+1;
distMap[val]=key;
}
map<int, int>::iterator p;
for(p = distMap.begin(); p != distMap.end(); p++) {
cout << p->first <<" occurs " <<p->second << endl;
}
cout << "seems legit: even distributed and correct" << endl;
return 0;
}
0
This c++ function should handle the task:
int getRandomIntExcludingRange(int start, int end, int start_range, int end_range) {
// handle bad input gracefully
if (start > end) {
std::swap(start, end);
}
if (start_range > end_range) {
std::swap(start_range, end_range);
}
std::clamp(start_range, start, end);
std::clamp(end_range, start, end);
auto range_length = end_range - start_range;
auto adj_end = end - range_length;
auto shifted_end = adj_end - start;
int rand_int = (rand() % shifted_end) + start;
if (rand_int >= start_range) {
rand_int = (rand_int - start_range) + end_range;
}
return rand_int;
}

brad
- 930
- 9
- 22