Click to See Complete Forum and Search --> : Random numbers in C
Charred_Phoenix
06-14-2003, 06:05 AM
Is there any way to generate random numbers WITHOUT easily discernable patterns?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
struct team {
int troops;
int score;
};
int seed = time(NULL);
int battles = 5;
int troops = 5;
struct team team1;
struct team team2;
team1.troops = troops;
team2.troops = troops;
printf("Dictionary challenge 1 - 'Skirmish'\n\n");
while(battles > 0) {
team1.score = randnum(seed);
team2.score = randnum(seed);
if(team1.score < team2.score) {
printf("Combat goes to team 1\n");
}
else {
printf("Combat goes to team 2\n");
}
battles--;
}
return 0;
}
int randnum(int seed) {
int randomnum;
srand(seed);
randomnum = drand48() * 10;
return randomnum;
}
You'll notice that the above will just alternate between the two teams. If you use rand instead of drand48 you avoid this, but two will always win, this will also happen if you change the seed based on time() each time you call randnum. Is there any way to generate more truely random numbers?
bwkaz
06-14-2003, 10:07 AM
Umm... you're using the same seed value for both random numbers. This means that both your random numbers will ALWAYS be the same! (perhaps not for drand48, I don't know how that function works)
You should seed the random number generator only once, probably when your program starts up. After that, there won't be any kind of discernible (to humans) pattern to the numbers, although if you use the same seed later, you will get the exact same sequence.
Cryptographic software uses /dev/urandom or /dev/random (the difference is that urandom will just return less-than-random data if the kernel doesn't have anything that it thinks is random enough, while random will block until it does). Open up the file, read in a couple of bytes (you don't want to read in too many), and use that as a seed, for example. Then close the file. :)
dchidelf
06-14-2003, 01:13 PM
Side note:
Here is some interesting reading on a random number generator:
http://www.irisa.fr/caps/projects/hipsor/HAVEGE.html
But, for a game, rand() would be enough I would think...
Charred_Phoenix
06-14-2003, 10:58 PM
bwkaz, if I use different seeds, 2 will always be greater than 1. (if they are based on time)
Also calling rand() repeatedly it gets larger and larger each time. Also I don't know what you mean by seeding it only once, I did. :-/
I'd prefer not to use /dev/urandom because it is too OS specific.
I'll try with that havege thing later, thanks.
Strogian
06-15-2003, 12:17 AM
team1.score = randnum(seed);
team2.score = randnum(seed);
Okay, two calls to randnum..
int randnum(int seed) {
int randomnum;
srand(seed);
randomnum = drand48() * 10;
return randomnum;
}
And each call seeds it. You don't need to do that. Random number generators produce a series of "pseudo-random" numbers based on the initial seed. So...
SEED: 5
27, 486, 29, 102, 587, 17, 6
RESEEDED: 5
27, 486, 29, 102, 587, 17, 6
If you use random seeds, then your program is random, no matter how many random numbers are generated from that single seed. You don't need to ever use two different seeds in your program. Once it's seeded, the random number generator is good to go. Just like putting an apple seed in the ground. Once you plant it and it grows into a tree, you can get as many apples as you want, for any purpose you want. You don't need to plant another seed to get a second apple. Ah..fun stuff.. :)
Oh, and that HAVEGE thing (stands for HArdware Volatile Entropy Gathering and Expansion) sounds a lot like /dev/random. That's what you'll want to use if you want the best randomness. But you don't really need to use it if you don't want to. If you do your time() call for the seed, and only seed it once, your program will be reasonably random. If someone really wanted to, he could manipulate the execution time to have a predictable seed, but you're probably not worried about that. ;)
bwkaz
06-15-2003, 01:37 PM
Originally posted by Charred_Phoenix
bwkaz, if I use different seeds, 2 will always be greater than 1. (if they are based on time) If your seed is going to be based on time, then you only want to seed it once, as has been posted.
But even if you do seed it twice, the first random number that you get back will (or should, based on the math used) not correlate in any way with the seed value.
Also calling rand() repeatedly it gets larger and larger each time. Also I don't know what you mean by seeding it only once, I did. :-/ That is ... very strange. Are you sure your system's rand() implementation works? What happens if you just loop, printing out 100 consecutive the results from rand() (don't bother seeding anything)?
Charred_Phoenix
06-16-2003, 03:03 AM
This has ended with me being thoroughly confused. No matter how I change the program I am unable to avoid a pattern that repeats everytime I run the program, can someone try and put together a working version of the program and then tell me how you got it to work? I know this is probably more than a little annoying for the people who have tried to help, but I don't know what's going on any more :(
Sepero
06-16-2003, 04:10 AM
I'm just now learning C++ (I don't know C), but I can easily see what your problem is. The easiest way to fix it(not the cleanest way), is to change these sections:
int seed = time(NULL);
int battles = 5;
int troops = 5;
struct team team1;
struct team team2;to this int seed = time(NULL);
srand(seed);
int battles = 5;
int troops = 5;
struct team team1;
struct team team2;
and this:
int randnum(int seed) {
int randomnum;
srand(seed);
randomnum = drand48() * 10;
return randomnum;
}to thisint randnum(int seed) {
int randomnum;
//srand(seed);
randomnum = drand48() * 10;
return randomnum;
}
You will need to figure out how you want to clean up your function. The seed integer will no longer need to be passed. :)
With the original set up, it returns the same number every time because the seed stays the same(and it re-seeds everytime, just before it gets the next number).
Good Luck.
Charred_Phoenix
06-17-2003, 03:22 AM
I did something very similar to that and noticed that the results were the same each time I ran it, I have now realised this was because I did all three in the same second >_<
Thanks, :)
Charred_Phoenix
07-03-2003, 10:52 PM
Well, I got board and tried to improve it again, but unfortunately I'm an idiot so it didn't work very well:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
struct team {
int troops;
int score;
};
int battles = 5;
int troops = 5;
struct team team1;
struct team team2;
team1.troops = troops;
team2.troops = troops;
srand(time(NULL));
printf("Dictionary challenge 1 - 'Skirmish'\n\n");
char **team1name;
printf("Team one name:");
scanf("%s", team1name);
char **team2name;
printf("\nTeam two name:");
scanf("%s", team2name);
printf("\n\n");
while((team1.troops != 0) & (team2.troops != 0)) {
team1.score = rand();
team2.score = rand();
if(team1.score < team2.score) {
printf("Combat goes to team 2\n");
team1.troops--;
}
else if(team1.score > team2.score) {
printf("Combat goes to team 1\n");
team2.troops--;
}
else {
printf("Both team members survived!");
}
battles--;
}
printf("Combat has ended with %d members of team one and %d members of team two.", team1.troops, team2.troops);
return 0;
}
:(
Erm, I should mention that this is a problem with dynamic data allocation, not random numbers.
Strogian
07-03-2003, 11:18 PM
Erm, I should mention that this is a problem with dynamic data allocation, not random numbers
Is the problem, that you're not doing any dynamic data allocation? :D
(hint: scanf doesn't allocate storage for you ;))
--actually, looks like the GNU version can do it, but not the way you're doing it there
another hint: get rid of one of the * on your teamnames. You only need one. :)
Charred_Phoenix
07-04-2003, 01:20 AM
I thought the way you dynamically allocated data was to use **dynamic-array or *dynamic-array[] :(
Strogian
07-04-2003, 09:52 AM
char **dynamic_array just creates a pointer to a pointer to a character.
You dynamically allocate data using malloc(). It allocates space, and returns a pointer to that space.
char *bob;
bob = malloc(10);
That's the same as
char bob[10];
(except you might want to free it later)
Charred_Phoenix
07-04-2003, 06:18 PM
Oh... ok...