17

I have seen many questions on SO about this particular subject but none of them has any answer for me, so I thought of asking this question.

I wanted to generate a random number between [-1, 1]. How I can do this?

Jacob
79k24 gold badges159 silver badges245 bronze badges
asked Oct 12, 2009 at 22:09
1
  • 3
    Since you did not specify float or int, return 0. Commented Oct 15, 2009 at 19:45

7 Answers 7

22

Use -1+2*((float)rand())/RAND_MAX

rand() generates integers in the range [0,RAND_MAX] inclusive therefore, ((float)rand())/RAND_MAX returns a floating-point number in [0,1]. We get random numbers from [-1,1] by adding it to -1.

EDIT: (adding relevant portions of the comment section)

On the limitations of this method:

((float)rand())/RAND_MAX returns a percentage (a fraction from 0 to 1). So since the range between -1 to 1 is 2 integers, I multiply that fraction by 2 and then add it to the minimum number you want, -1. This also tells you about the quality of your random numbers since you will only have RAND_MAX unique random numbers.

answered Oct 12, 2009 at 22:11
Sign up to request clarification or add additional context in comments.

13 Comments

This is creating error. "Expected Expression before float" and when i remove float around rand, it always generate -1.
It seems problematic since it will not create a contiguous random of decimal fractions but a discreet set of RAND_MAX numbers.
eyalm is right that it won't generate all possible floating point values between -1 and 1. It will generate RAND_MAX different ones (and RAND_MAX is usually 65535, so that might not be enough for a particular application). Still, for many purposes, this is sufficiently continuous.
@rmeador: The set of all possible floating point values is not uniformly distributed. If the smallest (positive) float is 10^-37, for instance, roughly half of the possible floating-point values lie between -(10^-18) and 10^-18.
Note that rand() returns integers in 0 to RAND_MAX inclusive, so you should actually divide by (RAND_MAX+1) to be exact. The difference does not matter much when RAND_MAX is say, 2147483647 (in which case note that RAND_MAX+1 can overflow), but it can be significant when RAND_MAX is only 32767.
|
10

If all you have is the Standard C library, then other people's answers are sensible. If you have POSIX functionality available to you, consider using the drand48() family of functions. In particular:

#define _XOPEN_SOURCE 600 /* Request non-standard functions */
#include <stdlib.h>
double f = +1.0 - 2.0 * drand48();
double g = -1.0 + 2.0 * drand48();

Note that the manual says:

The drand48() and erand48() functions shall return non-negative, double-precision, floating-point values, uniformly distributed over the interval [0.0,1.0).

If you strictly need [-1.0,+1.0] (as opposed to [-1.0,+1.0)), then you face a very delicate problem with how to extend the range.

The drand48() functions give you considerably more randomness than the typical implementation of rand(). However, if you need cryptographic randomness, none of these are appropriate; you need to look for 'cryptographically strong PRNG' (PRNG = pseudo-random number generator).

answered Oct 12, 2009 at 23:21

8 Comments

Er, a uniform distribution over [-1,1] is mathematically identical to a uniform distribution over [-1,1). The probability of getting exactly "1" is 0 in both cases.
@ShreevatsaR: err, if the generator says '[0.0,1.0)', it means there is a small but finite chance of obtaining the result 0.0, but there is no chance of getting 1.0 - it will never appear. Your argument would have to apply to the low-end of the range too. It is also interesting that my 'f' will contain values in the range (-1.0,+1.0] and my 'g' will contain values in the range [-1.0,+1.0).
Well, in a uniform distribution, the chance of obtaining any one particular exact value is 0 (not "small but finite"). Of course, an implementation might not correspond to the mathematical definition (for example, many implementations will return rational numbers with probability 1, while under an actual uniform distribution the set of rational numbers is countable and therefore has measure 0) — so I wonder what exactly "uniform distribution" means at all here. It could mean that for any x in [0,1) or [0,1], the probability of getting a number ≤ x is x. In which case, again, both are the same.
@ShreevatsaR: you're playing in a pure mathematical world; this site is about computer programming. You're splitting hairs meaninglessly. For instance, all double values are inherently rational numbers; there are no transcendental numbers stored in them, only (poor) approximations to the transcendental numbers.
Of course I know that; that's what I said in my previous comment. To reiterate/rephrase: for any good definition of uniform distribution (good w.r.t computer programming), whether you take [0,1] or [0,1) or (0,1] or (0,1) does not matter, because the extreme points 0 and 1 should not occur with any detectable probability. That's also why I upvoted your answer before commenting, because (contrary to the comment in it) it does give exactly what the question asks for. :-)
|
8

I had a similar question a while back and thought that it might be more efficient to just generate the fractional part directly. I did some searching and came across an interesting fast floating point rand that doesn't use floating point division or multiplication or a int->float cast can be done with some intimate knowledge of the internal representation of a float:

float sfrand( void )
{
 unsigned int a=(rand()<<16)|rand(); //we use the bottom 23 bits of the int, so one
 //16 bit rand() won't cut it.
 a=(a&0x007fffff) | 0x40000000; 
 return( *((float*)&a) - 3.0f );
}

The first part generates a random float from [2^1,2^2), subtract 3 and you have [-1, 1). This of course may be too intimate for some applications/developers but it was just what I was looking for. This mechanism works well for any range that is a power of 2 wide.

answered Oct 13, 2009 at 15:25

2 Comments

if RAND_MAX is the max of a short with the sign bit always positive only 15 bits will be random in the int returned. I'm not good with bit wise operations yet but from your comment that could be a problem.
Solution is to use only the first 1 byte from each of 4 calls to rand() .
6

For starters, you'll need the C library function rand(). This is in the stdlib.h header file, so you should put:

#include <stdlib.h>

near the beginning of your code. rand() will generate a random integer between zero and RAND_MAX so dividing it by RAND_MAX / 2 will give you a number between zero and 2 inclusive. Subtract one, and you're onto your target range of -1 to 1.

However, if you simply do int n = rand() / (RAND_MAX / 2) you will find you don't get the answer which you expect. This is because both rand() and RAND_MAX / 2 are integers, so integer arithmetic is used. To stop this from happening, some people use a float cast, but I would recommend avoiding casts by multiplying by 1.0.

You should also seed your random number generator using the srand() function. In order to get a different result each time, people often seed the generator based on the clock time, by doing srand(time(0)).

So, overall we have:

#include <stdlib.h>
srand(time(0);
double r = 1.0 * rand() / (RAND_MAX / 2) - 1;
answered Oct 12, 2009 at 22:54

3 Comments

Multiplying by 1.0 doesn't avoid the cast, it just makes it implicit. I'm not sure what you think you're gaining by "avoiding" the cast.
It certainly still performs a type conversion, but not via a cast, as the cast construct "(float)" is removed. Why is this better? Well, firstly "an unsuffixed floating constant has type double", so I'm doing the floating point arithmetic in double, rather than float. Secondly, using a cast construct turns off compiler warnings, and so should be avoided where possible. For example, if you mistyped rand() as another function which returns a pointer, the compiler will warn you if you attempt to multiply that by 1.0. However, if you mask that with a cast you lose helpful warnings.
that isn't a helpful warning, since you are indeed wanting to convert an int to a float.
3

While the accepted answer is fine in many cases, it will leave out "every other number", because it is expanding a range of already discrete values by 2 to cover the [-1, 1] interval. In a similar way if you had a random number generator which could generate an integer from [0, 10] and you wanted to generate [0, 20], simply multiplying by 2 will span the range, but not be able to cover the range (it would leave out all the odd numbers).

It probably has sufficiently fine grain for your needs, but does have this drawback, which could be statistically significant (and detrimental) in many applications - particularly monte carlo simulations and systems which have sensitive dependence on initial conditions.

A method which is able to generate any representable floating point number from -1 to 1 inclusive should rely on generating a sequence a1.a2 a3 a4 a5 ... up to the limit of your floating point precision which is the only way to be able to generate any possible float in the range. (i.e. following the definition of the real numbers)

answered Oct 12, 2009 at 23:06

2 Comments

Actually, this is a definition of real numbers :) There are quite a few different ones. Although the one that deos it through decimal notation is used by Knuth, so we should prefer it over all others :)
Indeed, it is the most immediately applicable to computational methods. en.wikipedia.org/wiki/Construction_of_the_real_numbers
1

From the "The C Standard Library"

int rand(void) - Returns pseudo-random number in range 0 to RAND_MAX

RAND_MAX - Maximum value returned by rand().

So:

rand() will return a pseudo-random number in range 0 to RAND_MAX

rand() / (double) RAND_MAX will return a pseudo-random number in range 0 to 1

2 * (rand() / (double) RAND_MAX) will return a pseudo-random number in range 0 to 2

2 * (rand() / (double) RAND_MAX) - 1 will return a pseudo-random number in range -1 to 1

answered Oct 12, 2009 at 22:54

2 Comments

Since you never cast the result of rand(), the division of RAND_MAX will always be 0.
Except in the case of rand() == RAND_MAX
0

As others already noted, any attempts to simply transform the range of 'rand()' function from [0, RAND_MAX] into the desired [-1, +1] will produce a random number generator that can only generate a discrete set of floating-point values. For a floating-point generator the density of these values might be insufficient in some applications (if the implementation-defined value of RAND_MAX is not sufficiently large). If this is a problem, one can increase the aforementioned density exponentially by using two or more 'rand()' calls instead of one.

For example, by combining the results of two consecutive calls to 'rand()' one can obtain a pseudo-random number in [0, (RAND_MAX + 1)^2 - 1] range

#define RAND_MAX2 ((RAND_MAX + 1ul) * (RAND_MAX + 1) - 1)
unsigned long r2 = (unsigned long) rand() * (RAND_MAX + 1) + rand();

and later use the same method to transform it into a floating-point number in [-1, +1] range

double dr2 = r2 * 2.0 / RAND_MAX2 - 1;

By using this method one can build-up as many 'rand()' calls as necessary, keeping an eye on integer overflow, of course.

As a side note, this method of combining consecutive 'rand()' calls doesn't produce very high quality pseudo-random number generators, but it might work perfectly well for many purposes.

Jonathan Leffler
759k145 gold badges961 silver badges1.3k bronze badges
answered Oct 13, 2009 at 3:15

1 Comment

Any attempt to transform anything into any range on a computer will produce a discrete set of rational values, floating-point or otherwise.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.