How to generate random numbers in C

P

pereges

I need to generate two uniform random numbers between 0 and 1 in C ?
How to do it ?

I looked into rand function where you need to #define RAND_MAX as 1
but will this rand function give me uniformly distributed and unique
numbers ?
 
I

Ian Collins

pereges said:
I need to generate two uniform random numbers between 0 and 1 in C ?
How to do it ?

I looked into rand function where you need to #define RAND_MAX as 1
but will this rand function give me uniformly distributed and unique
numbers ?

Why would you attempt to redefine RAND_MAX? If you want random numbers
between 0 and 1, assign the value of rand() to a double or float and
divide by RAND_MAX.

The distribution of the numbers returned by rand() isn't the best.
 
U

user923005

I need to generate two uniform random numbers between 0 and 1 in C ?
How to do it ?

If you have modern hardware and IEEE floating point, I recommend
dsfmt:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html
otherwise WELL512a.c and WELL512a.h from here:
http://www.iro.umontreal.ca/~panneton/WELLRNG.html

Are another possibility.
I looked into rand function where you need to #define RAND_MAX as 1
but will this rand function give me  uniformly distributed and unique
numbers ?

That is a read-only value for you. It's not something that you set,
it is something that you inquire upon.
 
O

osmium

pereges said:
I need to generate two uniform random numbers between 0 and 1 in C ?
How to do it ?

I looked into rand function where you need to #define RAND_MAX as 1
but will this rand function give me uniformly distributed and unique
numbers ?

There is useful information in the FAQ starting at about 13.15

http://www.c-faq.com/lib/index.html

A set of numbers shouldn't be random AND unique. One of the important
properties of a random number generator is that numbers can be repeated. To
provide what I understand you to want, look into "shuffle" as described in
13.19
 
R

Richard Tobin

pereges said:
I looked into rand function where you need to #define RAND_MAX as 1

RAND_MAX tells you what the maximum random number is. It doesn't
let you control it.
but will this rand function give me uniformly distributed and unique
numbers ?
I need to generate two uniform random numbers between 0 and 1 in C ?

rand() returns an integer between 0 and RAND_MAX. It's intended
to be uniformly distributed (though the standard doesn't seem to
say so) so you can get uniformly distributed random floating-point
numbers by something like

((double)rand()) / RAND_MAX

If you really need *unique* random numbers you're going to have to
do something more complicated. Are you sure you really do?

-- Richard
 
T

Thad Smith

Ian said:
Why would you attempt to redefine RAND_MAX?

Because then the rand() values will be between 0 and 1 as desired!
That is a logical thought process for someone starting out.
The distribution of the numbers returned by rand() isn't the best.

That depends on quality of implementation.
 
J

Joachim Schmitz

Thad said:
Because then the rand() values will be between 0 and 1 as desired!
That is a logical thought process for someone starting out.
I don't find that logical at all. RAND_MAX is defined in a header that comes
part of the implementation, so why should anyone come to the idea it might
be possible to modify it with the result being a library funcion of that
implementation to behave different?
It should be faily obvious, that a macro is used at compile time and that
the library funktion has been compiled quite a while ago, so won't be able
to tell if a macro got changed afterwards.

Bye, Jojo
 
R

Richard Tobin

Because then the rand() values will be between 0 and 1 as desired!
That is a logical thought process for someone starting out.
[/QUOTE]
I don't find that logical at all. RAND_MAX is defined in a header that comes
part of the implementation

But why would a beginner know that?
so why should anyone come to the idea it might
be possible to modify it with the result being a library funcion of that
implementation to behave different?

Perhaps they read the description in the standard that says "The rand
function copmuters a sequence of pseudo-random integers in the range
0 to RAND_MAX".

Anyway, you have just seen an example of someone who made this mistake,
so it's clear that it can be misunderstood. Arguing that it shouldn't
be doesn't help anyone.

-- Richard
 
J

Joachim Schmitz

I don't find that logical at all. RAND_MAX is defined in a header
that comes part of the implementation

But why would a beginner know that?[/QUOTE]
Because, (s)he'll find it on the disk after having install the compiler and
hasn't written this piece of code hime/herself. On a decently configured
system, using it as a non super user as it should be, (s)he even couldn't
make that modification due to file access permissions.
(And yes, I don't count Windows, up to XP at least, to this group, which
mostly requires you to work as Administrator or at least makes if very
difficult if you'r not)
Perhaps they read the description in the standard that says "The rand
function copmuters a sequence of pseudo-random integers in the range
0 to RAND_MAX".

Anyway, you have just seen an example of someone who made this
mistake, so it's clear that it can be misunderstood. Arguing that it
shouldn't be doesn't help anyone.
True, and I did neither. I just claimed it illogical to understand it that
way.

Bye, Jojo
 
K

Keith Thompson

Joachim Schmitz said:
Because, (s)he'll find it on the disk after having install the compiler and
hasn't written this piece of code hime/herself. On a decently configured
system, using it as a non super user as it should be, (s)he even couldn't
make that modification due to file access permissions.
(And yes, I don't count Windows, up to XP at least, to this group, which
mostly requires you to work as Administrator or at least makes if very
difficult if you'r not)

We weren't talking about modifying the file ("stdlib.h" or whatever)
that contains the implementation's definition of RAND_MAX; a newbie
likely wouldn't even know where to find it. We were talking about
redefining the macro in user code.

It's easy to assume that this:

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
#undef RAND_MAX
#define RAND_MAX 10 /* No, this won't work */
int i;
for (i = 0; i < 10; i ++) {
printf("%d\n", rand());
}
return 0;
}

will produce numbers in the range 0 to 10. It could even be made to
work if rand() is a macro. In fact, since redefining RAND_MAX invokes
undefined behavior, it could be made to work in a conforming (but
perverse) implementation.
 
U

user923005

Computers do not generate truly random numbers without hardware support.
Some techniques include the detection of radioactive decay and thermal
noise from a reverse-biased diode.  There is some belief that there
is randomness in the timing (say, down to picoseconds) of keystrokes,
although I don't think anyone has managed to tie human typing to quantum
effects yet.  Some CPU chips have hardware for random number generation
on them.

You may want pseudo-random numbers.  In cryptography, random numbers
are very important and the difference between pseudo-random numbers
and real random numbers used in encryption may get you killed as a
spy.

If you try to offer casino gambling games (e.g. craps, blackjack,
roulette, etc.) for real money using pseudo-random numbers, you're
going to lose.

The most important factor in gambling is the size of the house.
In a fair game, the player with the biggest house money volume wins.
Assuming a Markov process (random walk) the players will get ahead and
behind in a random, wobbling fashion. But as soon as the cash for one
player is gone, the game is over. If you have one hundred dollars and
the opponent has one trillion dollars, you are in a lot of trouble.
That's why I call gambling "A tax on stupidity." Of course if you
have a trillion dollars it's a good idea, but it isn't very nice in
that case.

There are PRNGs with a period so large it would not repeat if every
computer on earth ran it at full speed until the silicon wore out.
E.g. check out the period of the Mersenne Twister or WELL PRNGs.
rand() returns the same sequence of numbers each time the program
starts up unless you call srand() with a different seed value from
the last time.  Seed values are commonly derived from the time and/or
process ID (but NOT in applications where real random numbers are needed,
like gambling or cryptography:  32 bits of randomness isn't enough, and
a poor seed can cripple a good random number generator).

Another problem is that it is not always possible to know if a seed is
poor or not. Zero is a typical PRNG buster.
How to do it ?

There are better pseudo-random number generators than rand().
These have the disadvantage that they are not included in all C
libraries.
I looked into rand function where you need to #define RAND_MAX as 1

You do not get to redefine RAND_MAX.  Also, the return type of rand()
is int, so don't expect any values where 0 < rand() < 1 .  If RAND_MAX
were 1 (not allowed by the standard) all you would get is 0 and 1.
but will this rand function give me  uniformly distributed and unique
numbers ?

Consider using algebra.  rand() returns [0, RAND_MAX].  You want
numbers between 0.0 and 1.0 including both endpoints.  Or is that just
including 0.0 but not 1.0?  Consider what these might give you:

        ((double)rand())/RAND_MAX
or
        ((double)rand())/(RAND_MAX+1)

The problem with these [0,1] and [0,1) PRNGs is that they are *very*
grainy. They only give approximately RAND_MAX distinct values. If
you want something that is uniform between 0 and 1, it is likely to be
problematic unless only a very low quality PRNG is needed.
 
I

Ian Collins

Thad said:
Because then the rand() values will be between 0 and 1 as desired!

But rand() returns int.
That depends on quality of implementation.
OK, how about distribution of the numbers returned by rand() isn't
required to be the best.
 
W

Walter Roberson

Gordon Burditt said:
If you try to offer casino gambling games (e.g. craps, blackjack,
roulette, etc.) for real money using pseudo-random numbers, you're
going to lose.

I read a document describing the implementation of the electronic
games (e.g., slot machines) in a large real casino with many machines.
The numbers used were *not* true random numbers: they used a
complex algorithm that sent bursts of pseudo-random numbers to each
device, with the numbers sent out tweaked to dynamically alter the odds.
Thus when the central computer detected that a certain threshold of
money had come in, it would up the odds of winning so that there would
be a payout, to retain the long term house-odds they were licensed
to use by the appropriate gaming commission. Effectively, the casino
central computer would "pick" a machine have a jackpot on the basis
that it was time that -someone- won.

I do not recall now what was said about the manner in which the
pseudo-random bursts were generated; it was designed to make it
difficult to impossible for a human to predict, with the parameters
continually shifting. But the parameter shifts and numbers sent out
would be all carefully recorded to a write-once medium, so that if need
be afterwards the gaming commission or casino could examine the tapes
to ensure that the casino was not cheating the customers and that the
customers had not somehow cheated the casino.
 
U

user923005

Probably THE most important factor is the ability to cheat without
getting caught.  In this case, cheating involves predicting the
next random numbers so you know with some probability what the unseen
cards are.


Yes, even some of the partiipants in the office lottery ticket pool
say that.  Then they throw in their $3 per week into the pool.
And state lotteries have much lower prize per dollar gambled than
most casino games.

Right. It's about 30 cents per dollar, at least with one particular
lottery.
It doesn't matter (and the number of starting points is limited by
the number of possible seeds).  If I play thirty hands of blackjack
with the machine, (making minimal bets) and based on that I can
predict with 75% probability a strategy that will win from then on,
I've got a HUGE advantage.


Some people have suggested in this group a seed strategy that will
cripple the Mersenne Twister (or any PRNG, for that matter).
If there's only 32k or 64k possible seeds, it doesn't take too long
to eliminate most of them, and bet based on the remaining possibilities.

This Mersenne Twister only has 4 billion initial seeds:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c
(although the internal state vector is actually much larger than
that).

But the WELL PRNGs take a list of 32 ints for the initial state
vector. For most architectures that will be 2^1024 initial states
possible.

In decimal, it's:
1797 69313 48623 15907 72930 51907 89024 73361 79769 78942
30657 27343 00811 57732 67580 55009 63132 70847 73224 07536
02112 01138 79871 39335 76587 89768 81441 66224 92847 43063
94741 24377 76789 34248 65485 27630 22196 01246 09411 94530
82952 08500 57688 38150 68234 24628 81473 91311 05408 27237
16335 05106 84586 29823 99472 45938 47971 63048 35356 32962
42241 37216
differnt states.
The problem with these [0,1] and [0,1) PRNGs is that they are *very*
grainy.  They only give approximately RAND_MAX distinct values.  If

Well, the OP asked for something with that range, and using rand().
The range of [0,1] or [0,1) isn't what makes it grainy.  The grainy
part is a low value of RAND_MAX.
you want something that is uniform between 0 and 1, it is likely to be
problematic unless only a very low quality PRNG is needed.

Well, I could take the Mersenne Twister, call it a million times,
strip each result down to 32 bits, concatenate them, and add a
leading binary point.  Now I've got a pseudo-random number in the
range [0,1) with 32 million bits of mantissa.  That's not what I'd
call "grainy".  However, I don't have nearly that much randomness
in the seed I originally supplied.  If I'm just interested in
uniformity, not unpredictability, that may not matter.

The Mersenne Twister and WELL PRNGs produce double values between 0
and 1 with the full mantissa populated. They are also faster than
most PRNGs distributed with C compilers.
 
B

Bill Reid

There is no mathematical basis for this general statement, however,
there have been cases where people caught on to the sequence coming
from a poorly- or non-reseeded pseudo-random number generator
in a casino game and won hundreds of $thousands before the
casino realized their error...
The most important factor in gambling is the size of the house.

There is also no mathematical basis for THIS statement...you
guys are batting .000 again...
In a fair game, the player with the biggest house money volume wins.

Oh, a "fair game"...who the hell offers a "fair game"? In any event,
it's irrelevant, because the actual most important factor (to the extent
that we indulge in the pointless semantics of pronouncing a "most
important factor") is the "expectation" of the game.
Assuming a Markov process (random walk) the players will get ahead and
behind in a random, wobbling fashion. But as soon as the cash for one
player is gone, the game is over. If you have one hundred dollars and
the opponent has one trillion dollars, you are in a lot of trouble.

If you have a casino, and are stupidly offering a "fair game"
(0% "expectation"), you will eventually lose all your $trillion
to salaries and other expenses no matter how many individual
players come in and lose $100, because the money you win
from them will be offset by players who "get lucky" and win
$100, $200, $3000, or more...

You would be correct if you asserted that there is relationship
between the size of your "bankroll" and your average bet size
as a fraction of that "bankroll" in terms of actually acheiving
a result of "bankroll" growth (or non-loss) that conforms to
your "expectation" for the game. But that's a slightly more
complicated concept, innit?
That's why I call gambling "A tax on stupidity."

Stupidity is kind of its own tax, innit?
 
B

Bill Reid

I read a document describing the implementation of the electronic
games (e.g., slot machines) in a large real casino with many machines.

I'll do you one better: I worked as a consultant for companies that
produced these types of machines, and was intimately familiar with
their technical operation...
The numbers used were *not* true random numbers: they used a
complex algorithm that sent bursts of pseudo-random numbers to each
device, with the numbers sent out tweaked to dynamically alter the odds.
Thus when the central computer detected that a certain threshold of
money had come in, it would up the odds of winning so that there would
be a payout, to retain the long term house-odds they were licensed
to use by the appropriate gaming commission. Effectively, the casino
central computer would "pick" a machine have a jackpot on the basis
that it was time that -someone- won.

This would be totally illegal under Nevada state law, and presumably,
almost certainly, most gaming venues.
I do not recall now what was said about the manner in which the
pseudo-random bursts were generated; it was designed to make it
difficult to impossible for a human to predict, with the parameters
continually shifting. But the parameter shifts and numbers sent out
would be all carefully recorded to a write-once medium, so that if need
be afterwards the gaming commission or casino could examine the tapes
to ensure that the casino was not cheating the customers and that the
customers had not somehow cheated the casino.

Well, what you described would constitute de facto casino cheating
under Nevada state law...however, you are correct that a certain number
of game results are stored (but not necessarily in "write-once medium",
whatever that is), for various purposes, including checks by the
"Casino Control Commission" (or whatever it's called for the
particular venue).
 
B

Ben Bacarisse

Malcolm McLean said:
No, defining RAND_MAX as something else won't help. All it will do is
make the identifier useless in the rest of your program, without
touching the random number generator. Strictly it is UB in case
RAND_MAX appears in some standard library macro or other.

This is the generally accpeted way to do it
#define uniform() (rand() / (RAND_MAX + 1.0))
#define rnd(x) ( (x) * uniform() )

we add 1.0 to make rand() never return exactly unity, so rnd() is
always in the range 0 to x-1.

rnd(m) can be much closer to m than m-1. Did you mean:

#define rnd(x) ((int)((x) * uniform()))

perhaps? The OP wanted numbers between 0 and 1 so your uniform() is
sufficient if they mean doubles in [0,1).
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top