🔒 Locked
Random numbers?
Advertisement
Original Post
I have a problem with creating a random number and I could really use some help. I need to create a random integer between two integers, such as 12 and 16. I'm sure there is a simple solution to this, but it's eluding me. Do I need to use the ctime header file or do I need to create my own function for it? Could anyone show me how to code this? Thanks in advance, Mage
Quote:
Original post by mageofdreams
Thanks for the reply. I think I can use it now. Just one more question. Where does "assert" come from? I've never seen that before.
It is used by the debugger to ensure the condition is met while debugging. If the condition is false, then an error will be thrown to let you know something bad happened. It helps eliminate the need for checking code during release builds where you know the values should always be correct. Thus it helps gain some performance in your applications. However, it should not be used to replace all of your error checking code. Here this article explains it 100x's better then what I just have, check it out: Assert
I deleted my last post because I decided that no, I don't understand it after all... Sorry... I tried to use that code and couldn't get it to work. Could someone explain it to me?
And thanks for your explanation of the "assert" command. I don't think it will be helpful in my program because there won't be a way for min to be higher than max. But it's good to know anyway.
And thanks for your explanation of the "assert" command. I don't think it will be helpful in my program because there won't be a way for min to be higher than max. But it's good to know anyway.
Quote:
Original post by mageofdreams
I deleted my last post because I decided that no, I don't understand it after all... Sorry... I tried to use that code and couldn't get it to work. Could someone explain it to me?
All the magic is in the line:
std::rand() % (max - min + 1) + min
"std::rand()" gives you a random integer from 0 to RAND_MAX.
"std::rand() % N" gives you a random integer from 0 to (N-1). If you don't understand modulo (%) arithmetic, just think of it as the remainder after division.
"std::rand() % N + min" gives you a random integer from min to (min+N-1).
Therefore, if you want random integers from min to max, you need N such that "max = min + N - 1". A little algebra gives you "N = max - min + 1".
Putting in some actual numbers:
min = 12, max = 16
N = max - min + 1 = 16 - 12 + 1 = 5
"std::rand() % N" = "std::rand() % 5" which gives you a random integer from 0 to 4. If it returns its minimum, you'll end up with "12 + 0 = 12 = min"; if it returns its maximum, you'll end up with "12 + 4 = 16 = max". Anything else will be between these two values, as you required.
Quote:
And thanks for your explanation of the "assert" command. I don't think it will be helpful in my program because there won't be a way for min to be higher than max. But it's good to know anyway.
That's the whole point of assert. You're saying, "This condition can never happen unless something has gone horribly, horribly wrong". Thus, it tells you when things have gone horribly, horribly wrong.
What makes you so sure that min won't be higher than max?
EDIT: Note that assert should not be used for checking for errors that can only occur if there's a bug in your program. It should not, for example, be used to validate information passed by the user of the program or library.
Quote:Ah, but that's exactly what assert() is for. You use it to check a condition which should always be true under normal conditions: min is <= max, a pointer is non-null, the array index is in range, and so on.
Original post by mageofdreams
And thanks for your explanation of the "assert" command. I don't think it will be helpful in my program because there won't be a way for min to be higher than max.
With any program of sufficient complexity you as the programmer can't in general guarantee that there 'won't be a way' for a particular thing to happen. assert() alerts you to such problems as soon as they arise.
Quote:
Original post by Way Walker
All the magic is in the line:
std::rand() % (max - min + 1) + min
"std::rand()" gives you a random integer from 0 to RAND_MAX.
"std::rand() % N" gives you a random integer from 0 to (N-1). If you don't understand modulo (%) arithmetic, just think of it as the remainder after division.
"std::rand() % N + min" gives you a random integer from min to (min+N-1).
Therefore, if you want random integers from min to max, you need N such that "max = min + N - 1". A little algebra gives you "N = max - min + 1".
Putting in some actual numbers:
min = 12, max = 16
N = max - min + 1 = 16 - 12 + 1 = 5
"std::rand() % N" = "std::rand() % 5" which gives you a random integer from 0 to 4. If it returns its minimum, you'll end up with "12 + 0 = 12 = min"; if it returns its maximum, you'll end up with "12 + 4 = 16 = max". Anything else will be between these two values, as you required.
Not really adding to the OT, but using modulus (%) math to extract a value within a range from many random number generators is a pretty bad idea. Most generators have very poor randomness in the lowest bits of their output and modulus (%) isolates the worst bits
Check out boost::random for some very powerful and simple random-number functionality.
Quote:
Original post by Rockoon1
Not really adding to the OT, but using modulus (%) math to extract a value within a range from many random number generators is a pretty bad idea. Most generators have very poor randomness in the lowest bits of their output and modulus (%) isolates the worst bits
With most min/max pairs the higher bits will count just as much as the lower bits, if you really wanted a good randomness algorithm you shouldn't use std::rand in the first place since it usually doesn't have a very good distribution. It looks like the OP just wanted a pretty simple way to get a random number, and std::rand with modulus is quite good at that. If you want more control you should look into Boost.Random.
Quote:
Original post by CTar
With most min/max pairs the higher bits will count just as much as the lower bits
Absolutely incorrect
Typical pairs are (1, 2), (1, 16) and so forth... ie, a small range - these ranges only use the lowest few bits using the modulus method - in the first case it only uses the lowest bit, in the 2nd it uses only the lowest 4 bits.
Many generators alternate odd/even and thus have no randomness at all in the lowest bit!
Even wider ranges such as (1, 256), (1, 1024) only use the lowest 8 and 10 bits respectively.
Using the lowest bits should be a last resort (ie, you've used up all the upper ones) unless you are certain that the generator isn't an LCG.
if you really wanted a good randomness algorithm you shouldn't use std::rand in the first place since it usually doesn't have a very good distribution
[/QUOTE]
The distribution is worst when you insist on only using the lowest bits of an LCG.
When you have good psuedorandom bits comming out of std::rand but neglect to use them, it seems rather silly to solve what could easily be an imaginary problem with a drastic change.
Ahhh! I didn't know there would be so much math involved when I set out to do this. But I guess if I was afraid of math then I should never have started studying computer programming, lmao.
First of all, I finally got std::rand() to work, and I wrote this example code for myself:
{
int Max = 16;
int Min = 12;
int Result;
std::rand() % (Max - Min + 1) + Min == Result;
cout << "The result is " << Result;
return 0;
}
However, something's wrong because Result becomes 4198592! Am I missing a crucial step?
I looked at the links to "boost/random" but I don't think I'll try to implement that library now because I've had a lot of trouble linking external libraries to my programs in the past (like when I tried using DirectX9). It does seem helpful, but unnecessary right now.
I wish I could find a way to write my own random number function, but I can't figure out how. I'm not very good at math, as you might have guessed.
First of all, I finally got std::rand() to work, and I wrote this example code for myself:
{
int Max = 16;
int Min = 12;
int Result;
std::rand() % (Max - Min + 1) + Min == Result;
cout << "The result is " << Result;
return 0;
}
However, something's wrong because Result becomes 4198592! Am I missing a crucial step?
I looked at the links to "boost/random" but I don't think I'll try to implement that library now because I've had a lot of trouble linking external libraries to my programs in the past (like when I tried using DirectX9). It does seem helpful, but unnecessary right now.
I wish I could find a way to write my own random number function, but I can't figure out how. I'm not very good at math, as you might have guessed.
What makes you so sure that min won't be higher than max? [/QUOTE]
You're right, Way Walker, I should never assume that.
Thanks to everyone for their help so far.
Quote:
Original post by mageofdreams
Ahhh! I didn't know there would be so much math involved when I set out to do this.
This is much math? huh? Adding values and dividing values?
Quote:
First of all, I finally got std::rand() to work, and I wrote this example code for myself:
{
int Max = 16;
int Min = 12;
int Result;
std::rand() % (Max - Min + 1) + Min == Result;
cout << "The result is " << Result;
return 0;
}
However, something's wrong because Result becomes 4198592! Am I missing a crucial step?
a == b means comparison - check if value of a is equal to value of b.
a = b; means assign value of variable b to variable a.
You are comparing something you even do not want to.
You must write: Result = std::rand() % (Max - Min + 1) + Min;
Maybe read some tutorial about C++ or get a book before start programming?
Quote:
Original post by mageofdreams
{
int Max = 16;
int Min = 12;
int Result;
std::rand() % (Max - Min + 1) + Min == Result;
cout << "The result is " << Result;
return 0;
}
Try "Result = std::rand() % (Max - Min + 1) + Min;" instead of "std::rand() % (Max - Min + 1) + Min == Result;". What you have now compares some random integer with an uninitialized variable.
= for assignment
== for comparison
Quote:
I wish I could find a way to write my own random number function, but I can't figure out how. I'm not very good at math, as you might have guessed.
It'd help your understanding, but you really should just use some library's implementation.
By the way, if you're wondering about how to improve upon the % method (which everyone's complaining about) try:
Result = std::rand() / (RAND_MAX / (max - min + 1) + 1) + min;
Quote:
Original post by bubu LV
Maybe read some tutorial about C++ or get a book before start programming?
Ha. You're funny. The confusion of the two operators was just a mistake. I think I confused myself, in fact, because when I used the "=" operator I got a compiler error, so I thought I must have the uses of each one switched. But thanks for making that clear.
Ahh, it finally works! But it bugs me that each time I run the program it uses the exact same number. Maybe it won't do that in practice, though.
Quote:
Original post by Way Walker
By the way, if you're wondering about how to improve upon the % method (which everyone's complaining about) try:
Result = std::rand() / (RAND_MAX / (max - min + 1) + 1) + min;
The two methods don't seem to work any differently. But I'll use this method since everyone seems to think that it's better.
Once again, thanks very much for the help! I'm going to write all of this down so I don't forget.
You need to seed the random number generator in order to get it to produce a different sequence. You do this by calling std::srand(). A typical approach is to use the current system time as a seed, which is pretty decent:
std::srand(std::time(NULL));
Be sure to #include <ctime> to get access to std::time.
std::srand(std::time(NULL));
Be sure to #include <ctime> to get access to std::time.
Quote:
Original post by mageofdreams Quote:
Original post by Way Walker
By the way, if you're wondering about how to improve upon the % method (which everyone's complaining about) try:
Result = std::rand() / (RAND_MAX / (max - min + 1) + 1) + min;
The two methods don't seem to work any differently. But I'll use this method since everyone seems to think that it's better.
For an ideal rand() they should be "equivalent" (that is, equally approximate a uniform random distribution). The key difference is that this new version uses division while the old version uses the modulus/remainder.
Think of it like this. Take a number and divide it by, say, 10 to get the quotient and the remainder. Now, add 1 to that number and, again, find the quotient and the remainder. Now, add 1 again and find the quotient and remainder one last time. You should see that adding a small number will affect the remainder but leaves the quotient relatively unaffected. In my head, I think of this as the modulus depending on the "small portion" of the number (technically, the low order bits) and division depending on the "large portion" of the number (technically, the high order bits).
The problem is that many implementations of std::rand() are random enough in the "large portion" but not very random in the "small portion". (To get a feel for why this is, check out Linear congruential generators at Wikipedia and note that this common method depends strongly on the modulus for randomness. Note that the form from Numerical Recipes in C that the article mentions was actually a common implementation of std::rand().)
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement