views:

386

answers:

10

How does one make random numbers in the interval -10 to 10 in C++ ?

srand(int(time(0)));//seed
for(int i  = 0; i < size; i++){
 myArray[i] = 1 + rand()  % 20 - 10;//this will give from -9 to 10
 myArray2[i] =rand()  % 20 - 10;//and this will -10 to 9
}
+1  A: 

You've got a fencepost error -- the range you're interested in is one larger than the modulo you were using; instead try:

myArray2[i] =rand()  % 21 - 10;//and this will -10 to +10
Rowland Shaw
A: 

rand() % 21 - 10

Toon Van Acker
+8  A: 

You need a range of 21, not 20, so do something like this:

x = rand() % 21 - 10;
Paul R
Just to add to this... The reason is that there are actually 21 possibilities.... count them out. 0 is included.
Mark
Note that using naïve modulus will have a bias towards smaller numbers. If you need uniformity then you'll need to reject some numbers `rand()` returns.
Joey
rand() generates numbers from 0..RAND_MAX where RAND_MAX is library dependent but must be at least 32767. If RAND_MAX%21!=0 you have higher probabilities to get certain numbers. In most of practical applications it doesn't really matter but in some scientific calculations this may seriously affect the calculation results.
zoli2k
@zoli2k: Well noted - still, for a scientific calculation I wouldn't rely on built-in rand() anyway.
peterchen
Why the down-vote ? With no comment ?
Paul R
A: 

If you want the numbers to be in the range [-10, 10], then you have 21 possible numbers.

(rand() % 21) - 10;
Matthew T. Staebler
+4  A: 

You can generate random numbers between [0,20] using rand() % 21 and then subtract 10 from every generated number.

codaddict
A: 

How about (rand() % 21) - 10; ?

Or am I missing something here?

Richard Inglis
+8  A: 

Use the Boost Random Number Library. The built-in random number generator has a notoriously poor distribution quality. Moreover, boost provides you a lot of useful generators.

// based on boost random_demo.cpp profane demo
#include <iostream>

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>

int main() {
  boost::mt19937 gen(42u); // seed generator
  boost::uniform_int<> uni_dist(-10, 10); // random int from -10 to 10 inclusive
  boost::variate_generator<boost::mt19937&, boost::uniform_int<> > 
    uni(gen, uni_dist); // callable

  for(int i = 0; i < 10; i++)
    std::cout << uni() << ' ';
}

Output:

-3 6 9 -7 5 6 2 2 -7 -1 
Danvil
+1. It even gives you a function that generates you a number from a range. Without all that hassle of doing it wrong :-)
Joey
+9  A: 

To get uniform distribution you must divide with RAND_MAX first

static_cast<int>(21*static_cast<double>(rand())/(RAND_MAX+1)) - 10

using

rand() % 21 - 10;

is faster and is often used in applications but the resulted distribution is not uniform. Function rand() generates numbers from from 0 to RAND_MAX. If RAND_MAX%21!=0 lower numbers are generated with higher probability.

You may also consider to use the modulo method but with dropping of some of the random numbers:

int randMax = RAND_MAX - RAND_MAX%21;

int p=RAND_MAX+1;
while(p>randMax)
        p=rand();

x=p%21 - 10;

Edit (comments from Johannes and Steve):

When dividing with RAND_MAX there are some numbers from the range which will be picked more often so the proper way to handle is to reject numbers which would lead to an uneven distribution on the target interval.

Using the Boost Random Library (mentioned by Danvil) all the problems with uniformity of random numbers are eliminated.

zoli2k
Using modulus instead of division is a much neater way to get random integers.
Danvil
@Danvil It is faster but wrong. It doesn't produce a uniformly distributed random numbers.
zoli2k
@danvil: what do you mean with "neater"? Using modulus does not return an evenly distributed random number, as both zoli2k and smt has explained here. I upvoted the answer to remove the downvote.
Terje Mikal
You have a bug in your RAND_MAX solution. You shouldn't multiply it with 21 but with 20 instead. Now you get numbers from -10 to 11.
smt
Convinced. But if one wants a good distribution, rand is the wrong function at all. It produces poor distributions even in 0-RAND_MAX. So for a quick and dirty implementation % does not much wrong.
Danvil
@smt Multiplying with 21 is correct.
zoli2k
@zoli2k Well think about it. When rand() returns RAND_MAX, the division is 1. 21*1 is 21. 21 - 10 is 11. So multiplying with 21 is incorrect, you should multiply with 20.
smt
@Danvil I think the quality of rand is implementation dependent.
zoli2k
@Danvil: As bad as LCGs are, they're not *that* bad. Depending on the application the bias you introduce with improper handling will be much worse. zoli2k: Dividing by `RAND_MAX` will *also* bias the result; it's just that the numbers that will be more often picked are now *somewhere* in the range, instead of the lower end. The fact that there *is* bias doesn't change at all.
Joey
@smt U are right. Fixed.
zoli2k
@Johannes Can you describe this bias in more details when dividing with `RAND_MAX`? I don't get it.
zoli2k
@zoli2k: Suppose for the sake of argument that RAND_MAX is 2^16-1. So there are 65536 possible results of `rand()`. There are 21 possible results of your function. Since 65536 is not a multiple of 21, it is not possible for your function to produce a uniform distribution. Some of the 21 outcomes must be more common than others, it just isn't immediately obvious which.
Steve Jessop
You're still dividing 32768 (or whatever RAND_MAX is) numbers on a range of numbers which doesn't have to divide evenly. You still have the problem that there some numbers from the range will be picked more often. Look at it another way: If RAND_MAX is 25 and you'll try fitting that to a range with just 24 numbers, then there has to be *one* number which gets picked twice as often as the others. The proper way to handle this is to reject numbers which would lead to an uneven distribution on the target interval. Java's Random class has a nice implementation of this.
Joey
Dividing instead of using modulus is not done in order to "get a uniform result", it's done in order to work around the fact that an LCG (and hence `rand()`) has trivial relations between consecutive outputs (serial correlation). For example, `rand()` may well produce alternately odd and even results, so if you mod with an even number then you'd preserve this property. Hence the advice to use division with `rand()`. It still doesn't give uniformity, it improves things by giving the (better-varying) high bits of the output more influence than the (serially correlated) low bits.
Steve Jessop
@zoli2k: if you are worrying abou the distribution of numbers. The don't use the default random generator but resort to something more sophisticated like the mersenne twister algorithm
Toad
@Steve: Depending on the generator it doesn't have to have bad lower bits, though. Marsaglias's Recursion with Carry generator generates wirse bits at the upper end, for example.
Joey
@johannes rossel: if MAX_RND is significantly high (and it usually is), that discarding all numbers until they meet the criteria (lower than 21 in this case) would be an enormous performance hit. Like I said earlier, if you worry about the distribution, you should not even bother with the default random anyways.
Toad
@reinier: You don't discard all numbers larger than 21. You discard all numbers larger than `RAND_MAX / n * n` because *those* are the ones you need to worry about skewing the distribution.
Joey
@Johannes: sure, and RC4 doesn't have any bad bits. It's just that the advice was invented when LCG was common, and to be fair it still is pretty common for `rand()`, although I think sometimes implementations drop the lowest bits or otherwise fix it a bit. Nobody who cares about the results uses `rand()` anyway, surely?
Steve Jessop
A: 

use this will work:

int x = (rand() % 21) - 10;
cout<<x;
ninovsnino
A: 

You could use Knuth's subtractive random number generator to generate a number, 'u' in (0,1) and then use this simple linear equation to get a random number in [-10,10]:

-10*u + (1-u)*10
Amit