turning Marsaglia's recent posts into a function

U

Uno

For reasons various and sundry, I want to create a capability to produce
a random letter. For a source of randomness, I have used C's rand()
and fortran's random_seed. Writing with these functions wouldn't be any
fun.

Is there someplace on ubuntu that I could draw random ints from?

That might not be topical, but what is the following:

$ gcc -Wall -Wextra geo1.c -o out
geo1.c: In function ‘MWC’:
geo1.c:5: warning: type defaults to ‘int’ in declaration of ‘c’
geo1.c:5: warning: type defaults to ‘int’ in declaration of ‘j’
geo1.c:5: warning: unused variable ‘i’
geo1.c: In function ‘main’:
geo1.c:21: warning: format ‘%22u’ expects type ‘unsigned int’, but
argument 2 has type ‘long unsigned int’
geo1.c:23: warning: format ‘%22u’ expects type ‘unsigned int’, but
argument 2 has type ‘long unsigned int’
geo1.c:24: warning: control reaches end of non-void function
$ ./out
MWC result=3740121002 ?
3740121002
KISS result=2224631993 ?
2224631993
$ cat geo1.c
static unsigned long xs=521288629,xcng=362436069,Q[4691];

unsigned long MWC(void) /*takes about 4.2 nanosecs or 238 million/
second*/
{unsigned long t,x,i; static c=0,j=4691;
j=(j<4690)? j+1:0;
x=Q[j];
t=(x<<13)+c+x; c=(t<x)+(x>>19);
return (Q[j]=t);
}

#define CNG ( xcng=69069*xcng+123 )
#define XS ( xs^=(xs<<13), xs^=(xs>>17), xs^=(xs<<5) )
#define KISS ( MWC()+CNG+XS ) /*138 million/sec*/

#include <stdio.h>
int main()
{unsigned long i,x;
for(i=0;i<4691;i++) Q=CNG+XS;
for(i=0;i<1000000000;i++) x=MWC();
printf(" MWC result=3740121002 ?\n%22u\n",x);
for(i=0;i<1000000000;i++) x=KISS;
printf("KISS result=2224631993 ?\n%22u\n",x);
}

// gcc -Wall -Wextra geo1.c -o out
$

I think Dann Corbit cleaned up George's post after this, but I'm sitting
here completely stumped as to how I would make this a function. I don't
think this function needs a seed, so:

long georges_rand(void);

and then that's only one line of code away from

char georges_rand(void);

For the life of me, I don't see how you'd pull a number from this
routine that is different on another run.

Thanks for your comment, and cheers,
 
I

Ian Collins

For reasons various and sundry, I want to create a capability to produce
a random letter. For a source of randomness, I have used C's rand() and
fortran's random_seed. Writing with these functions wouldn't be any fun.

Is there someplace on ubuntu that I could draw random ints from?

That might not be topical, but what is the following:

$ gcc -Wall -Wextra geo1.c -o out
geo1.c: In function ‘MWC’:
geo1.c:5: warning: type defaults to ‘int’ in declaration of ‘c’
geo1.c:5: warning: type defaults to ‘int’ in declaration of ‘j’
geo1.c:5: warning: unused variable ‘i’
geo1.c: In function ‘main’:
geo1.c:21: warning: format ‘%22u’ expects type ‘unsigned int’, but
argument 2 has type ‘long unsigned int’
geo1.c:23: warning: format ‘%22u’ expects type ‘unsigned int’, but
argument 2 has type ‘long unsigned int’
geo1.c:24: warning: control reaches end of non-void function

A list of compiler warnings for some truly awful code.
 
J

James

Uno said:
For reasons various and sundry, I want to create a capability to produce a
random letter. For a source of randomness, I have used C's rand() and
fortran's random_seed. Writing with these functions wouldn't be any fun.

Is there someplace on ubuntu that I could draw random ints from?

Does Ubuntu have /dev/random?

[...]
 
U

Uno

Ian said:
On 09/ 1/10 12:42 PM, Uno wrote:

A list of compiler warnings for some truly awful code.

These things look very fixable to me. George is 86, so he remembers a
more traditional C and has forgotten more about making random numbers
than we'll ever know.

I don't think he reads clc, but do you think your tone appropriate?
 
U

Uno

Keith said:
Yes. "man 4 random".

I guess I don't know what I'm seeing here.


// gcc -D_GNU_SOURCE -Wall -Wextra a1.c -o out
$ indent -i3 a1.c
$ gcc -D_GNU_SOURCE -Wall -Wextra a1.c -o out
$ ./out
1804289383
$ ./out
1804289383
$ cat a1.c

#include <stdlib.h>
#include <stdio.h>
// get a pseudorandom
int
main ()
{
long ran;
ran = random ();
printf ("%ld\n", ran);
return 0;
}

// gcc -D_GNU_SOURCE -Wall -Wextra a1.c -o out
$

Why the repeated value in the output?

on the other hand I try to cat it and get:

$ pwd
/dev
$ ls
adsp net sg0 tty36
usbdev1.2_ep00
agpgart network_latency sg1 tty37

....
kmem ram8 tty21 tty6 vcs5
kmsg ram9 tty22 tty60 vcs6
log random tty23 tty61 vcs7
....
mixer1 sequencer2 tty35 usbdev1.1_ep81 zero

$ cat random
Iݻ�՘�A�:�i��n��ĘIU�ci�\F�a8�^i��kY+��}���O�پ��<#���c_!�,��e�EʺSP�'Q^C
$ man random
$

I think there must be a well established path how to make use of these
numbers on *nix with C.
 
I

Ian Collins

These things look very fixable to me. George is 86, so he remembers a
more traditional C and has forgotten more about making random numbers
than we'll ever know.

I don't think he reads clc, but do you think your tone appropriate?

Yes.

unsigned long t,x,i; static c=0,j=4691;

is an abomination.

Passing the wrong types to printf is a bug.
 
B

BartC

That might not be topical, but what is the following:
static unsigned long xs=521288629,xcng=362436069,Q[4691]; ....
printf("KISS result=2224631993 ?\n%22u\n",x);
I think Dann Corbit cleaned up George's post after this, but I'm sitting
here completely stumped as to how I would make this a function. I don't
think this function needs a seed, so:

long georges_rand(void);

and then that's only one line of code away from

char georges_rand(void);

For the life of me, I don't see how you'd pull a number from this routine
that is different on another run.

Perhaps:

unsigned long kiss(void){return KISS;}

Used as follows:

printf("Kiss1 = %lu\n",kiss());
printf("Kiss2 = %lu\n",kiss());
etc.

From main(), you have to retain the Q[] setup code (put into an init
routine). The two big loops are just test code and can be dispensed with.

Not sure about the difference between MWC and KISS, but the latter is more
elaborate so might be the one to use.

Don't know how the seeds (presumably xs and xcng) are set up: whether you
can put anything in them, or whether they need a special form.

To get a random letter, you have to turn the 32-bit results into a number
between 'A' and 'Z'. There's any number of ways, most of which will not be
randomly distributed; but I might try something like (for ASCII):

kiss()/165191050+'A';
 
B

Ben Bacarisse

Uno said:
I guess I don't know what I'm seeing here.

// gcc -D_GNU_SOURCE -Wall -Wextra a1.c -o out
$ indent -i3 a1.c
$ gcc -D_GNU_SOURCE -Wall -Wextra a1.c -o out
$ ./out
1804289383
$ ./out
1804289383
$ cat a1.c

#include <stdlib.h>
#include <stdio.h>
// get a pseudorandom
int
main ()
{
long ran;
ran = random ();
printf ("%ld\n", ran);
return 0;
}

// gcc -D_GNU_SOURCE -Wall -Wextra a1.c -o out
$

Why the repeated value in the output?
http://c-faq.com/lib/srand.html

$ pwd
/dev
$ cat random
$ man random

You need to pop over to comp.unix.programmer and ask there. The first
question to ask is how do use man to find out about /dev/random.
I think there must be a well established path how to make use of these
numbers on *nix with C.

That's a question for comp.unix.programmer.
 
U

Uno

Ben said:

I didn't see anything relevant there. I don't intend to make a rand()
call. I'm gonna read what's in dev/random. rand() would make no use of
dev/random unless written implementation specifically, so I suppose it
could, but it "shouldn't have to."
You need to pop over to comp.unix.programmer and ask there. The first
question to ask is how do use man to find out about /dev/random.

I left out the 4. Ok
That's a question for comp.unix.programmer.

Alright, now I've read man random and man 4 random, and my question follows:

What do you have to do with dev/random to harness it for random number
generation in C? It's absurd to think that I'm going to seed it.
That's not the answer.

Do I slap a FILE * on it somehow?
 
B

Ben Bacarisse

Uno said:
I didn't see anything relevant there.

As far as I can see it answers your question exactly. OK, you are using
random() rather than rand() but I prefer not point out the obvious.
I don't intend to make a rand()
call. I'm gonna read what's in dev/random. rand() would make no use
of dev/random unless written implementation specifically, so I suppose
it could, but it "shouldn't have to."

I think you think there is a connection between random() and
/dev/random. The answer to your question about the program that uses
random() is answered by the FAQ (with reference to rand() but the issue
is the same). Whatever you might want to do with /dev/random is a
matter for another group.

I'll leave the rest since you cross-posted this and, presumably, the
unix people will answer your unix questions.

<snip>
 
K

Keith Thompson

Ben Bacarisse said:
As far as I can see it answers your question exactly. OK, you are using
random() rather than rand() but I prefer not point out the obvious.

I think he's using /dev/random, not the random() function. ("man
random" typically gives you information about the random() function;
"man 4 random" gives you information about the /dev/random device.)
I think you think there is a connection between random() and
/dev/random. The answer to your question about the program that uses
random() is answered by the FAQ (with reference to rand() but the issue
is the same). Whatever you might want to do with /dev/random is a
matter for another group.

Since rand() is *required* to give the same sequence of numbers for
a given seed, it can't really use /dev/random, which is designed
to be unpredictable.

[...]
 
I

Ike Naar

Alright, now I've read man random and man 4 random,

Then by now you know that the random() function and /dev/random
have the name in common, but are really different beasts.

Use random() (the function) to get predictable, seedable pseudo-random numbers.
random() is supposed to give better quality pseudo-random numbers than rand(),
but it works on the same principles: an algorithm that computes a sequence
of numbers, based on an input seed.

Use /dev/random (the device) to get unpredictable random numbers.
The data in /dev/random is generated by the operating system from
unpredictable sources (like keyboard-, network- or disk i/o events).
and my question follows:
What do you have to do with dev/random to harness it for random number
generation in C? It's absurd to think that I'm going to seed it.
That's not the answer.

Correct, you don't seed /dev/random (at least, not explicitly).
In a way, you implicitly seed it by using certain parts of the system.
Do I slap a FILE * on it somehow?

Slapping is not necessary. Just open the file for reading and read from it.
Here's a small C example:

#include <stdio.h>

int main(void)
{
FILE *f = fopen("/dev/random", "rb");
if (f != NULL)
{
unsigned int data;
if (1 == fread(&data, sizeof data, 1, f))
{
printf("%u\n", data);
}
fclose(f);
}
return 0;
}
 
B

Ben Bacarisse

Keith Thompson said:
I think he's using /dev/random, not the random() function.

No. He wrote a program that uses random() and asked why he gets the
same results every time it runs. The FAQ explains this perfectly well
albeit with reference to rand() rather than random().
("man
random" typically gives you information about the random() function;
"man 4 random" gives you information about the /dev/random device.)

That may well be why he wrote the program that uses random() rather than
/dev/random but surely it's OK for me to comment on what he asked rather
than on whatever off-topic question I might guess he wanted to ask.
Since rand() is *required* to give the same sequence of numbers for
a given seed, it can't really use /dev/random, which is designed
to be unpredictable.

So is random() what is why the FAQ answer is suitable.
 
R

Rainer Weikusat

(e-mail address removed) (Ike Naar) writes:

[...]
Slapping is not necessary. Just open the file for reading and read from it.
Here's a small C example:

#include <stdio.h>

int main(void)
{
FILE *f = fopen("/dev/random", "rb");
if (f != NULL)
{
unsigned int data;
if (1 == fread(&data, sizeof data, 1, f))
{
printf("%u\n", data);
}
fclose(f);
}
return 0;
}

And here is the same example as a sensibly implemented UNIX(*) program:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(void)
{
unsigned u;
ssize_t nr;
int fd;

fd = open("/dev/random", O_RDONLY, 0);
if (fd != -1) {
nr = read(fd, &u, sizeof(u));
if (nr == sizeof(u)) printf("%u\n", u);
}

return 0;
}
 
K

Keith Thompson

Ben Bacarisse said:
No. He wrote a program that uses random() and asked why he gets the
same results every time it runs. The FAQ explains this perfectly well
albeit with reference to rand() rather than random().

Argh, you're right; I didn't look at enough of the context. And yes,
random() and srandom() behave similarly to the standard rand() and
srand().

[...]
 

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,818
Messages
2,569,732
Members
45,691
Latest member
Dick331194

Latest Threads

Top