# Thread: How to generate a random number in the interval of -1 and 1?

1. ## How to generate a random number in the interval of -1 and 1?

If R is a random number, R has to be in the interval of -1 and 1, i.e, -1<R<1. Any idea? 2. Do you know how to get a random value in an interval of 0 to 2?
And... are you sure you need to exclude -1 and 1? 3. If it is an integer -1 < x < 1 then it doesn't leave many options.... 4. Originally Posted by hamster_nz If it is an integer -1 < x < 1 then it doesn't leave many options....
INCLUDING these two is, of course, very easy. Excluding them is easy too, but there is a trick.

Of course, I'm waiting to see some code before showing it...  5. The problem of the following formula(value = 2.0 * (rnumber - 0.5)), it provides sometimes -1 or +1 once the rnumber is 0 or 1.

Code:
```#include<stdio.h>
#include<iostream>
int main()
{
float rnumber, value;
for (int i = 0; i < 1000000; i++)
{
rnumber = (double)rand() / (double)((unsigned)RAND_MAX);
value = 2.0 * (rnumber - 0.5);

if (value == -1 || value == 1) printf("%7.4f    ", rnumber);
}
return 0;
}``` 6. My soluction: Reducing precision by 1 ULP.

Code:
```#include <stdlib.h>
#include <math.h>
#include <float.h>

// Transform rand() return value to [-1.0 e 1.0] range.
#define XFRM_RAND(x) ( 2.0 * (double)(x) / RAND_MAX - 1.0 )

// OBS: 'double' because 'float' has only 24 bits of precision.
double rand_simetrical ( void )
{
double f, ulp;
int e;

f = XFRM_RAND ( rand() );

// Calculate ULP.
frexp ( f, &e );
ulp = ldexp ( DBL_EPSILON, e - 1 );

if ( f >= 0.0 )
ulp = -ulp;

// Get rid of 1.0 and -1.0 by making all values 1 ULP less precise.
f += ulp;

return f;
}``` 7. Another possibility. Generates values from -0.999999999068677 to 0.999999999068677, inclusive.
Code:
```#include <stdio.h>
#include <stdlib.h>
#include <time.h>

double rndx()
{
return ((unsigned)rand() + 1) / (double)((unsigned)RAND_MAX + 2) * 2.0 - 1.0;
}

int main()
{
srand(time(NULL));

printf("Low: %.15f\n", ((unsigned)0 + 1)
/ (double)((unsigned)RAND_MAX + 2) * 2.0 - 1.0);
printf("High: %.15f\n\n", ((unsigned)RAND_MAX + 1)
/ (double)((unsigned)RAND_MAX + 2) * 2.0 - 1.0);

for (int i = 0; i < 10; ++i)
printf("%.15f\n", rndx());

return 0;
}``` 8. Originally Posted by john.c Another possibility. Generates values from -0.999999999068677 to 0.999999999068677, inclusive.
Interesting the use of casting to unsigned int to avoid overflows. I have only 1 consideration:

RAND_MAX not necessarily is INT_MAX. It could be UINT_MAX. But, of course, rand() returns an int... It is safe to think as RAND_MAX is INT_MAX.

Anyway... I think this approach is very good!

PS: Sorry... your approach doesn't cause problems with the distribution, AFAIK... 9. Hummm... sorry again, john.c... Taking another look, your approach use the range between -0.999999999068677425384521484375 and 0.999999999068677425384521484375, inclusive. Mine is wider, from -0.999999999999999777955395074968691915273666381835 9375 and 0.999999999999999777955395074968691915273666381835 9375, inclusive.

Notice 1/RAND_MAX gives us a step of 2⁻³¹ (for RAND_MAX as INT_MAX). Your approach has an "error" of, approx, 9.3*10⁻¹⁰, witch gives us a step of approx 2⁻³⁰. This means half of possible values returned by rand() have duplicates in that range.

Well... my approach has a potential for exactly 2 duplicates only. If I got DBL_EPSILON or -DBL_EPSILON as result of the equation (never happens because 2⁻³¹ is very far from that epsilon). 10. Since rand() returns an int, obviously RAND_MAX, "the maximum value returned by the function rand," cannot be UINT_MAX.

Also, double's only have a precision of 15-17 decimal digits, so showing them to 30 (or 50) digits is meaningless.

I don't understand what you mean by "duplicates". Different values from rand() obviously yield different values as a double. There are no duplicates.

As for you "wider range", that's an artifact of your method which has an artifically high step between rand() returns of 0 and 1 and between RAND_MAX-1 and RAND_MAX.

Your method is overcomplicated and simply not worth it.

BTW, what does "simetrical" mean? 11. Also, double's only have a precision of 15-17 decimal digits, so showing them to 30 (or 50) digits is meaningless.
That's a common mistake. The precision of a floating point type is measured in bits, not decimal digits. In the case of a `double` type, using IEEE 754 format, if you have all the 53 bits set (the implicit one and all the 52 fracional) and an expoent of 0 in the "scale factor", the exact value represented will be 1.999999999999999777955395074968691915273666381835 9375 with these 53 decimal digits.

The 15-16 decimal digits equivalence is an approximation based on the transformation from binary to decimal, as in:

p = log10(2⁵³) = 53*log10(2)

It means that not all decimal values can be represented exactly in binary (take 0.1 as an example, which is 0b0.000111001100... ad infinitum), so if you want an approximation you can take only 15 or 16 decimal digits and round to nearest, to be sure.

Not all decimal values can be represented, exactly, in binary but ALL binary values has an exact correspondence in decimal.

As for you "wider range", that's an artifact of your method which has an artifically high step between rand() returns of 0 and 1 and between RAND_MAX-1 and RAND_MAX.

Your method is overcomplicated and simply not worth it.
Why "artifically"? ULP is a consistent concept when using floating point values. All I did was to add/subtract 1 ULP, the smallest possible value based on a calculated value to avoid reaching 1.0 or -1.0.

1- Get a random value in [0,1] range, multiply by 2 and subtract 1 to get [-1,1];
2- Subtract (or add) 1 ULP

I think this is less complicated to understand why 2*(r+1)/(R+2)-1 works as well. By the way, the same equation could be written as:
Code:
```double rndx( void )
{ return ( 2.0 * rand() - RAND_MAX) / (RAND_MAX + 2.0); }```
No casting needed and no need to worry about overflows.

BTW, what does "simetrical" mean?
Sorry... "symmetrical". Anyway: what "artifically" means? 12. In time: You are correct about the duplicates. There are none. My mistake. 13. Originally Posted by Shafiul If R is a random number, R has to be in the interval of -1 and 1, i.e, -1<R<1. Any idea?
define two macros. One is uniform(), which create a random number on 0-1. The other is lerp, which interpolates between a and b by paramter t, on 0-1.

So
Code:
`x = lerp(-1.0, 1.0, uniform());`
Usually uniform() is implemented to return a value on 1 to 1 - epsilon, so you will never actually get 1 returned. This might or might not be acceptable. 14. That's interesting, Malcom! I completely forgot about linear interpolation!

Code:
```#include <stdlib.h>
#include <float.h>

#define lerp(min_, max_, norm) \
( (min_)*(1.0 - (norm)) + (max_)*(norm) )

double symmetrical_rand ( void )
{
double d;

d = ( double ) rand() / RAND_MAX;
return lerp ( -1.0 + DBL_EPSILON, 1.0 - DBL_EPSILON, d );
}``` 15. Me? I would most likely do what I did when I needed random numbers that were inside a sphere. Generate random numbers between -1 and 1 (inclusive), and if it s >= 1.0 or <= -1.0 then just loop and try again.... so

Code:
```    do {
x = (double)rand()/RAND_MAX*2.0-1.0;
while(x <= -1.0 || x >= 1.0);``` Popular pages Recent additions #### Tags for this Thread

generate, i.e, interval, number, random 