5

OK, most probably it will be marked as duplicated, but I am looking for an answer and cannot find something similar. The question is: I want to generate random numbers within a specific range [i.e. min_value to max_value] and with a specific step. For the first part the answer is:

int random_value = rand() % max_value + min_value;

The step how can I define it? I suppose that the above mentioned solution results in step 1. Correct? And if for example I want to generate the numbers with step 2 (e.g. 2, 4, ..., 16) what should I do?

RE60K
  • 621
  • 1
  • 7
  • 26
kat
  • 97
  • 7
  • 2
    Multiply `rand()` by `step`? – Stefano Sanfilippo Dec 15 '14 at 10:58
  • Better tell us what do you want to accomplish, because this seems like an xy problem. – bitcell Dec 15 '14 at 10:59
  • 1
    Stefano Sanfilippo by multiplication you are loosing the minimum value – kat Dec 15 '14 at 11:02
  • does step means that value is divisible be step – RE60K Dec 15 '14 at 11:03
  • Unicell I am not sure what I am not explaining well. I have a number of possible values for some parameters of my program. One parameter for example may take the values from 0 to 9 with step one and another one from 24 to 44 with step 2. In each iteration I want to pick the parameter values randomly. The first one is easy. The second one it confuses me. – kat Dec 15 '14 at 11:05
  • Just divide the min and max by the step, choose a random number between these two (equivalent to having a step of one), and at the end multiply the result by the step to have a value between your initial min and max. – tomaoq Dec 15 '14 at 11:23

2 Answers2

3

This should do what you want:

int GetRandom(int max_value, int min_value, int step)
{
    int random_value = (rand() % ((++max_value - min_value) / step)) * step + min_value;
    return random_value;
}
Vality
  • 6,577
  • 3
  • 27
  • 48
  • This works, but it excludes the max_value. If for example I want the values to be from 24 to 44 with step 2, the 44 is not included. I know that it is easy to solve it (define 46 instead of 44), but it would be confusing. – kat Dec 15 '14 at 11:09
  • Ok, now you are missing a bracket – kat Dec 15 '14 at 11:14
  • @kat you should simply be able to increment maxvalue first actually. – Vality Dec 15 '14 at 11:16
  • Yes, this is an option. Thank you Vality. – kat Dec 15 '14 at 11:17
  • This generates random numbers that are biased. For some values the bias will be quite noticable. See: [How to generate a random number from within a range](http://stackoverflow.com/questions/2509679/how-to-generate-a-random-number-from-within-a-range/6852396?s=1|0.0000#6852396) – Nisse Engström Dec 15 '14 at 11:49
  • @NisseEngström You are indeed right, however I am assuming that from the OPs usage of rand already that they do not require a uniform distribution. Or at least that the level of uniformity and size of the numbers is such that it suits their requirements. – Vality Dec 15 '14 at 11:54
  • 2
    If `(++max_value - min_value)` is not a multiple of `step`, bias occurs in addition to that mentioned by @Nisse Engström. But then OP is not clear on the requirements in that case. – chux - Reinstate Monica Dec 15 '14 at 17:35
  • @chux In this case yes it is a multiple of the step. So you have already given a solution to my problem. Now about the bias, and what Nisse and Clifford say... I think I'll go to the kitchen to wash some dishes. Thank you – kat Dec 16 '14 at 08:04
2

Your "first step" is ill-advised since it suffers from modulo bias.

Introducing a "step" is a matter of simple arithmetic, you generate a random number on a smaller range min_value / step to max_value / step and multiply that by your required step (random_value * step).

So:

#include <stdint.h>
#include <stdlib.h>
int random_range( int min_value, int max_value )
{
    // Fix me
    return rand() % max_value + min_value;
}

int random_range_step(  int min_value, int max_value, int step )
{
    return random_range( min_value / step, max_value / step ) * step ;
}

...

//  (e.g. 2, 4, ..., 16)
int random_value = random_range_step( 2, 16, 2 ) ;
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • Thank you Clifford for your help. – kat Dec 15 '14 at 11:28
  • You have replaced the modulo operator with the division operator. This does not get rid of the bias, as the article you linked to will explain. – Nisse Engström Dec 15 '14 at 12:17
  • @NisseEngström : I was careless with that. I have changed the solution to use the `rand()/RAND_MAX` quotient, but rearranged to avoid floating point and using a larger type for the intermediate value so it will work for the full RAND_MAX range. Also fixed range for min to max *inclusive*. It is simpler than the solutions suggested in the link, and what I had intended. – Clifford Dec 15 '14 at 17:19
  • Confident there is an off-by-one problem. Consider `random_range(0, RAND_MAX)`. Code should be `.../(RAND_MAX+1)` rather than `.../RAND_MAX`. – chux - Reinstate Monica Dec 15 '14 at 17:30
  • You've managed to spread the bias over the whole range. Let's assume, for the sake of simplicity, that `RAND_MAX == 65535`, and examine how `random_range(0, 49999)` causes each of the `rand()` return values to fall into the 50000 "buckets": **bucket[0]: 2** values, **buckets[1-2]: 1** value each, **bucket[3]: 2** values, and so on. That's an astonishing bias! – Nisse Engström Dec 15 '14 at 21:00
  • 1
    @NisseEngström As it is not really part of the question and is probably a distraction, I have left it as a note and used the original flawed code for simplicity. (i.e. I gave up! Solutions are well documented elsewhere). – Clifford Dec 15 '14 at 23:02