views:

484

answers:

13

I'm making a game in c++ and it involves filling tiles with random booleans (either yes or no) whether it is yes or no is decided by rand() % 1. It doesnt feel very random. I'm using srand with ctime at startup, but it seems like the same patterns are coming up. Are there any algorithms that will create very random numbers? Or any suggestions on how I could improve rand()?

Thanks

+1  A: 

Boost Random Number Library

ceretullis
+1  A: 

The perfect way of Yes or No as random is toggling those. You may not need random function.

S.Mark
Is it just me... or is that not very random at all...
LorenVS
It's not, and the OP said he needs random values.
Loadmaster
+1, @LorenVS- As random as anything else could possibly be in an entirely deterministic universe.
instanceofTom
Ok, I could delete this, but came to think that, "OP doesnt feel very random.", I think he got something like "Yes Yes Yes Yes Yes No", and he/she might think it doesn't random
S.Mark
Almost like `int random() { return 4; } // Completely random chosen number`.
Cecil Has a Name
... By fair roll of a D6. I get more randomness from my collection of D% dice, and they have an odd knack for rolling a fairly consistent 88%.
greyfade
A: 

The lowest bits of standard random number generators aren't very random, this is a well known problem.

I'd look into the boost random number library.

Mark Ransom
+13  A: 

True randomness often doesn't seem very random. Do expect to see odd runs.

But at least one immediate thing you can do to help is to avoid using just the lowest-order bit. To quote Numerical Recipes in C:

If you want to generate a random integer between 1 and 10, you should always do it by using high-order bits, as in
j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
and never by anything resembling
j = 1 + (rand() % 10);
(which uses lower-order bits).

Also, you might consider using a different RNG with better properties instead. The Xorshift algorithm is a nice alternative. It's speedy and compact at just a few lines of C, and should be good enough statistically for nearly any game.

Boojum
Avoiding low-order bits depends very much on the generator. Some PRNGs generate weak *high-order* bits instead.
Joey
+1  A: 

Many pseudo-random number generators suffer from cyclical lower bits, especially linear congruential algorithms, which are typically the most common implementations. Some people suggest shifting out the least significant bits to solve this.

Loadmaster
A: 

Also if you reseed too fast then you will get the exact same number. Personally I use a class that updates the seed only when the time has changed.

Why would you ever reseed?
Claudiu
You should never re-seed.
Martin York
It's less random if you don't reseed.
Its NOT random if you re-seed.
Martin York
rand() goes through a sequence designed to be random (sort of), as long as you keep going. If you re-seed then you start a new sequence. There are no guarantees about the relationship of the two sequences.
Martin York
If you reseed with the same number martin then ya. I am talking about reseeding with the time when it is different.
@high6: No. That is exactly what I am talking about. You seed once when the application starts then you don't re-seed again. Otherwise you are defeating the purpose of the seed. To start a random sequence.
Martin York
If you never reseed then it is even less random.
You need to read a book on random :-)
Martin York
Here. Look at this example: http://padfly.com/RandomTest
Martin York
Martin, when comparing don't just "simulate". http://padfly.com/high6/random
Please note you are already on -2. The reason it seems closer to my number is that you are actually only re-seeding about 4 times (depending on the speed of your processor). The more you re-seed the less random it becomes. And digging further. Your new example is even worse. GetTickCount() repeats every 49 days and thus is not a good seed for random. So not only are you numbers random or evenly distributed your are seriously jeopardy of repeating a sequence. time() on the other hand only repeats every 60 years.
Martin York
Actually, if you are drawing *lots* of numbers you have to re-seed eventually, especially if you are exhausting the numeric range of the PRNG return type. Generating pseudo-random numbers is actually drawing balls from a bowl *without putting them back.* So if you use very large amounts of numbers (or, for some PRNGs not so large ones) you are hurting your randomness. Still, updating the seed periodically is a Bad Idea™ as then yuo'll get a linear dependence of the seeds which hurts your randomness even more. You can re-seed if you're something like halfway through the period of the PRNG.
Joey
This whole discussion just proves that random is not a trivial subject. Unless you really know what you are doing you should be using libraries that do the work for you. Please take a look at the boost random libraries.
Martin York
@Johannes: Very true. But that's way beyond this discussion.
Martin York
Martin: Agreed :-) Still, not all "rules" how to treat PRNGs apply in every case :-)
Joey
Yup, because being -2 means you are instantly wrong no matter what. Anyways, thanks for at least explaining it Johannes. I get what you mean. Although wouldn't that depend on the random algorithm being used?
It *always* depends on the algorithm. As Martin already said, pseudo-random numbers are not trivial and re-seeding blindly without knowing what *exactly* you're doing will very likely hurt you. The problem is, that unless something goes *catastrophically* wrong you won't notice that your output is flawed. Re-seeding every second should be such a case. There are numerous papers on that subject, too. And still, I think the −2 is appropriate here (even though I didn't downvote). The advice *is* bad. I just noted that blindly recommending never to re-seed doesn't work in the general case too.
Joey
A: 

A quick thing that might make your numbers feel a bit more random would be to re-seed the generator each time the condition if(rand() % 50==0) is true.

instanceofTom
What ... exactly does that condition tell you about the need to re-seed?
Joey
Depending on the range of the numbers being generated, and the number generator, it will *(should)* automatically re-seed the generator 1 out of every 50 (or whatever) numbers generated
instanceofTom
Note that "feel more random" does not equal better statistical randomness properties. PRNGs are fickle things, especially when treated improperly or without very precise knowledge what one is doing (and even then they can explode back into your face).
Joey
+6  A: 

The low order bits are not very random.
By using %2 you are only checking the bottom bit of the random number.

Assuming you are not needing crypto strength randomness.
Then the following should be OK.

bool  tile = rand() > (RAND_MAX / 2);
Martin York
Actually, by using %1 they're not even using the bottom bit. :)
Shmoopty
That's funny. Fixed.
Martin York
Your solution has the same problem as the original one: using only one bit of rand()'s return value. The OP uses only the lowest bit, your solution uses only the highest bit. A better solution would use all bits.
sbk
@sbk: If I think on it hard yes you are correct. I was just simplifying 'rand()/(RAND_MAX + 1.0) * RANGE' Where the range is 2.
Martin York
A: 

People say lower-order bits are not random. So try something from the middle. This will get you the 28th bit:

(rand() >> 13) % 2
Claudiu
Have fun with the Microsoft CRT with this. A nice, endless stream of zeros :-)
Joey
yees it'd be better to use 13 in that case
Claudiu
A: 

Knuth suggests a Random number generation by subtractive method. Its is believed to be quite randome. For a sample implementation in the Scheme language see here

Amit
As good a book as TAoCp is, that one is pretty dated and *a lot* has happened in PRNG research in the past 20 years. The subtractive method isn't much better than an LCG, actually.
Joey
+1  A: 

I have used the Mersenne Twister random number generator successfully for many years. Its source code is available from the maths department of Hiroshima Uni here. (Direct link so you don't have to read Japanese!)

What is great about this algorithm is that:

  1. Its 'randomness' is very good
  2. Its state vector is a vector of unsigned ints and an index, so it is very easy to save its state, reload its state, and resume a pseudo-random process from where it left off.

I'd recommend giving it a look for your game.

mcdave
Show me any PRNG where the second quoted advantage *doesn't* hold. That's pretty much a standard feature of PRNGs, actually.
Joey
+3  A: 
Joey
A: 

With random numbers to get good results you really need to have a generator that combines several generators's results. Just discarding the bottom bit is a pretty silly answer.

multiply with carry is simple to implement and has good results on its own and if you have several of them and combine the results you will get extremely good results. It also doesn't require much memory and is very fast.

Charles Eli Cheese
You don't need to combine generators to get good results, you just need to use a good generator. Also, combining generators without knowing what you are doing is likely to produce poor results.
Steve S