How to generate random number between two numbers

S

Sanchit

I want to generate a randowm number between two numbers x and y i.e

int randomNoBetween(int x, int y);

Plz help
Is there any such function??
 
D

Daniel Kraft

Sanchit said:
I want to generate a randowm number between two numbers x and y i.e

int randomNoBetween(int x, int y);

The (I guess) simplest way to get a random number in the interval [0, n)
(that is, 0 inclusive, n exclusive) is (if n is small enough) probably
(rand() % n), which will however slightly favor smaller numbers.

I can't tell if there's any "consensus" on whether to use this method or
some more expensive (like floating point arithmetic) to do this.

With this method, it is trivial to write your function in question; this
is left as an exercise to you ;)

Daniel
 
V

vippstar

See question 13.16 of the C-FAQ.
The (I guess) simplest way to get a random number in the interval [0, n)
(that is, 0 inclusive, n exclusive) is (if n is small enough) probably
(rand() % n), which will however slightly favor smaller numbers.

Yes, see question 13.18 of the aforementioned FAQ to learn why.
 
G

Gene

Sanchit said:
I want to generate a randowm number between two numbers x and y i.e
int randomNoBetween(int x, int y);

The (I guess) simplest way to get a random number in the interval [0, n)
(that is, 0 inclusive, n exclusive) is (if n is small enough) probably
(rand() % n), which will however slightly favor smaller numbers.

You can eliminate the bias by computing the largest multiple of
RAND_MAX that's evenly divisible by n. Call this M. Then just throw
away random numbers until you get one in the range 0 to M-1. Call
this R. Then return R % n.
 
B

Ben Bacarisse

See question 13.16 of the C-FAQ.
The (I guess) simplest way to get a random number in the interval [0, n)
(that is, 0 inclusive, n exclusive) is (if n is small enough) probably
(rand() % n), which will however slightly favor smaller numbers.

Yes, see question 13.18 of the aforementioned FAQ to learn why.

I don't see how 13.18 helps to explain this bias at all.

13.18 explains why some generators have poor low order bits. Gene has
explained how to remove the bias from reducing the range. It might be
worth pointing out that for n <<< RAND_MAX you can generally ignore
the bias though not the low-order bit problem.
 
S

Sanchit

Generating random numbers requires specialized hardware.  Do you
want pseudo-random numbers instead?  There's a big difference,
especially to those using cryptography.





Generally, you can take whatever pseudo-random number generator you
have that generates numbers in a range you can't control, and use
algebra to transform that range into the one you want.  Sometimes
this will result in inaccurate probability distribution.

I have to generate a pseudo random number
 
K

Keith Thompson

Sanchit said:
On Sep 29, 11:36 pm, (e-mail address removed) (Gordon "rude" Burditt) wrote: [...]
Generally, you can take whatever pseudo-random number generator you
have that generates numbers in a range you can't control, and use
algebra to transform that range into the one you want.  Sometimes
this will result in inaccurate probability distribution.

I have to generate a pseudo random number

You *have* to? Why?

Did you have a question beyond what you asked originally? Did the
extensive discussion and references in this thread not answer your
question?
 
B

Bartc

Sanchit said:
I want to generate a randowm number between two numbers x and y i.e

int randomNoBetween(int x, int y);

Given a function random() which generates a (necessarily) pseudo-random
integer with enough bits for your purpose:

/* Return random number from x to y inclusive */
int randomNoBetween(int x, int y) {
return (random() %(y-x+1))+x;
}

You will have to find your own random(); I just use something like this:

#include <stdlib.h>

int random() {
return (rand()<<15) | rand();
}
 
B

Ben Bacarisse

Bartc said:
Given a function random() which generates a (necessarily)
pseudo-random integer with enough bits for your purpose:

/* Return random number from x to y inclusive */
int randomNoBetween(int x, int y) {
return (random() %(y-x+1))+x;
}

You will have to find your own random(); I just use something like this:

#include <stdlib.h>

int random() {
return (rand()<<15) | rand();
}

Eek! The general advice is to leave a PRNG alone unless you know it
has a fault and your fix is correct for it. I've seen more problems
caused by "fixed" PRNGs than by intrinsically bad ones.

The above is not a good idea. It has probable undefined behaviour (on
most systems) and will produce badly biased results if RAND_MAX is not
65535.
 
B

Bartc

Ben Bacarisse said:
Eek! The general advice is to leave a PRNG alone unless you know it
has a fault and your fix is correct for it. I've seen more problems
caused by "fixed" PRNGs than by intrinsically bad ones.

The above is not a good idea. It has probable undefined behaviour (on
most systems) and will produce badly biased results if RAND_MAX is not
65535.

Last check I checked, rand() only returned a 15-bit result. And just quickly
checking again the 3 compilers I use, they are still all 15-bits.

Still, perhaps that second rand() can be &-ed with 32767 just in case.

A RAND_MAX of 32767 is too low.
 
B

Ben Bacarisse

Correction to self: I meant 32767 and I think you got that.
Last check I checked, rand() only returned a 15-bit result. And just
quickly checking again the 3 compilers I use, they are still all
15-bits.

That does not mean the advice is good. Just say: "with my C lib
RAND_MAX is 32767 so I do..." and you won't get a comment (except the
one below). It looked like general advice and as such it us unwise.
Still, perhaps that second rand() can be &-ed with 32767 just in
case.

I would not do that. If the & is needed to avoid the bias of
overlapping bits then the whole construct is ill-advised.
A RAND_MAX of 32767 is too low.

I agree, but halving the period of a bad PRNG in exchange for doubling
the bits per call is not always a good idea. It may be worth it in
your case (I have no idea why you are doing it) but, again, it is not
really sound advice /in general/.
 
B

Bartc

Ben Bacarisse said:
That does not mean the advice is good. Just say: "with my C lib
RAND_MAX is 32767 so I do..." and you won't get a comment (except the
one below). It looked like general advice and as such it us unwise.


I would not do that. If the & is needed to avoid the bias of
overlapping bits then the whole construct is ill-advised.


I agree, but halving the period of a bad PRNG in exchange for doubling
the bits per call is not always a good idea. It may be worth it in
your case (I have no idea why you are doing it) but, again, it is not
really sound advice /in general/.

I did suggest the OP find his own random() function; this was just an idea.

In my case this use of rand() is used to build a function (actually in
another language) that returns a random real (float) in the range 0.0..1.0,
or an integer in the range a..b, exactly as the OP required.

For both these purposes I really need more than 15 bits.

The actual performance of my random() functions I've always tried out with a
wallpaper test, and for my not very serious purposes seems adequate.
 
R

Richard Tobin

Still, perhaps that second rand() can be &-ed with 32767 just in
case.
[/QUOTE]
I would not do that. If the & is needed to avoid the bias of
overlapping bits then the whole construct is ill-advised.

I disagree. If you have a source that provides at least 15 random
bits (which, modulo poor quality of implementation, rand() is
required to do), and you need some larger number of random bits,
then sticking together chunks of 15 bits is a reasonable approach.

You could be more sophisticated and examine RAND_MAX to see how many
bits you get, but it would be somewhat tedious especially as I don't
think it's guaranteed that RAND_MAX is of the form 2^n-1.

-- Richard
 
K

Keith Thompson

Bartc said:
Last check I checked, rand() only returned a 15-bit result. And just
quickly checking again the 3 compilers I use, they are still all
15-bits.

RAND_MAX must be at least 32767 (and at most INT_MAX). It's
2147483647 on two systems I just tried. (BTW, RAND_MAX is an
attribute of the runtime library, not of the compiler.)
Still, perhaps that second rand() can be &-ed with 32767 just in case.

A RAND_MAX of 32767 is too low.

If you mean it's too low for your purposes, I won't disagree, but it's
allowed by the standard.

Your random() function (note that there's a POSIX function by that
name, so you might want to pick something else), with the "&32767"
added, produces 30 bits of randomness. You might consider checking
whether RAND_MAX is big enough, and if so, just call rand() once:

int rand30(void)
{
#define BITS15 0x7fff
#define BITS30 0x3fffffff
#if RAND_MAX >= BITS30
return rand() & BITS30;
#else
return (rand() & BITS15) << 15 | (rand() & BITS15);
#endif
}
 
B

Ben Bacarisse

I would not do that. If the & is needed to avoid the bias of
overlapping bits then the whole construct is ill-advised.

I disagree. If you have a source that provides at least 15 random
bits (which, modulo poor quality of implementation, rand() is
required to do), and you need some larger number of random bits,
then sticking together chunks of 15 bits is a reasonable approach.[/QUOTE]

Oh sure. If you need more bits then shifting, masking and or-ing is
fine. It was the idea that bunging in a mask would fix the specific
code that prompted my comment. If the mask is needed then the code is
in danger of producing UB.
You could be more sophisticated and examine RAND_MAX to see how many
bits you get, but it would be somewhat tedious especially as I don't
think it's guaranteed that RAND_MAX is of the form 2^n-1.

No, but if you don't inspect RAND_MAX and make the code depend on it
in some way you are in danger of shifting too much.
 
C

CBFalconer

Bartc said:
.... snip ...


Last check I checked, rand() only returned a 15-bit result. And
just quickly checking again the 3 compilers I use, they are still
all 15-bits.

Still, perhaps that second rand() can be &-ed with 32767 just in
case.

A RAND_MAX of 32767 is too low.

Then install a good random mechanism. For example, the source code
for cokusmt.h and cokusmt.c is included in my nmmalloc.zip package,
and implements the Mersenne twister. This package is in the public
domain, so you can use it freely. My (minor) corrections to make
it purely standard C coding have not been checked on systems with
longs larger than 32 bits, so such use is caught and signalled.
Nobody has checked it out in such a location yet.

See: <http://cbfalconer.home.att.net/download/nmalloc.zip>
 
R

Richard Tobin

You could be more sophisticated and examine RAND_MAX to see how many
bits you get, but it would be somewhat tedious especially as I don't
think it's guaranteed that RAND_MAX is of the form 2^n-1.
[/QUOTE]
No, but if you don't inspect RAND_MAX and make the code depend on it
in some way you are in danger of shifting too much.

You can rely on RAND_MAX being at least 32767, so if you only use
15 bits you don't have to inspect it.

-- Richard
 
R

Richard Bos

_If_ your rand() is good enough (and there is no guarantee that it is),
you can simply get 30 bits of pseudo-randomness, even using the usual
15-bit rand(), with

long twice_rand(void)
{
return (rand()&32767)<<15 + rand()&32767;
}

and even more by repeating this method. However, I do not recommend
this.
Then install a good random mechanism. For example, the source code
for cokusmt.h and cokusmt.c is included in my nmmalloc.zip package,
and implements the Mersenne twister.

Neither do I recommend the MT for most people and most purposes. Yes, it
is very good, but it is also complex and uses a lot of state. And it's
quite slow, for a PRNG. In other words, if you're running an on-line
casino, it's not good enough (you want _real_ randomness for that); if
you're running nearly anything else, it's too good; AFAICT, the MT is
the thing for you only if you run Monte Carlo simulations of quantum or
astronomical systems.
For most people, I'd recommend using something simpler than MT, yet
better than the Standard example of rand() (which, remember, is a
_minimal_ implementation). For example, in the message to this newsgroup
with Message-ID <S%[email protected]> (you
should be able to find it on any good news archive, and also on Google
Groups), George Marsaglia talks about a 32-bit-minus-one PRNG which is
not perfect, but very good for most uses, easy to implement, and quite
swift. It's simply this (with seed function added by me):

uint32_t seed=1; /* Must be a 32-bit, unsigned type. Can't be zero,
and won't ever reach zero through this PRNG. */

uint32_t threeshift_srand(const uint32_t newseed)
{
uint32_t oldseed=seed;

if (newseed)
seed=newseed;

return oldseed;
}

/* Returns a PRN between 0 and 2**32 - 1. */
uint32_t threeshift_rand(void)
{
seed^=seed<<13; seed^=seed>>17; seed^=seed<<5;
return seed-1;
}

Even if you don't use that PRNG, a search of posts to this group by
George Marsaglia will probably tell you more about PRNGs than the rest
of us put together could teach you.

Richard
 
C

CBFalconer

Richard said:
.... snip ...


Neither do I recommend the MT for most people and most purposes.
Yes, it is very good, but it is also complex and uses a lot of
state. And it's quite slow, for a PRNG. In other words, if you're
running an on-line casino, it's not good enough (you want _real_
randomness for that); if you're running nearly anything else,
it's too good; AFAICT, the MT is the thing for you only if you run
Monte Carlo simulations of quantum or astronomical systems.

Well, I suggest postponing worrying about speed until you find it
affects you. The system I recommended above is quite fast, but it
will occasionally take a few extra microsecs to prepare a new
batch. I have had no problems with it for many millions of calls.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,019
Latest member
RoxannaSta

Latest Threads

Top