Rand generating same numbers - c++

I have a problem with the small game that I made.
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
int span = 100;
srand(time(0));
int TheNumber = static_cast<double> (rand()) /RAND_MAX * (span -1) +1;
cout << "You need to guess the number between 1 and " << span << endl;
int mynumber;
int numberofAttempts = 0;
do {
cout << ++numberofAttempts <<" Attempt: ";
cin >> mynumber;
if (mynumber > TheNumber)
cout <<"Lower!" << endl;
else if (mynumber < TheNumber)
cout <<"Higher!" << endl;
} while (mynumber != TheNumber);
cout << "SUCESS!!!" << endl;
return 0;
}
The game is supposed to generate a random number between 0-100 and you are supposed to guess it. After running this code 15-20times the same numbers generated some even 8 times (the number 2 in my case).
I know that there is no absolute random number and that it uses some math formula or something to get one.I know that using srand(time(0)) makes it dependent on the current time. But how would I make it "more" random, since I don't want the stuff to happen that I mentioned above.
First time I ran it the result was 11, after running it again (after guessing the right number) , it was still 11, even though the time changed.

[ADDITION1]
If you DO truly wish to look into better random number generation, then this is a good algorithm to begin with:
http://en.wikipedia.org/wiki/Mersenne_twister
Remember though that any "Computer Generated" (i.e. mathematically generated) random number is ONLY pseudo-random. Pseudo-random means that while the outputs from the algorithm look to have normal distribution, they are truly deterministic if one knows the input seed. True random numbers are completely non-deterministic.
[ORIGINAL]
Try simply one of the following lines:
rand() % (span + 1); // This will give 0 - 100
rand() % span; // this will give 0 - 99
rand() % span + 1; // This will give 1 - 100
Instead of:
(rand()) /RAND_MAX * (span -1) +1
Also, don't cast the result of that to a double, then place into an int.
Look here also:
http://www.cplusplus.com/reference/clibrary/cstdlib/rand/
In Response to the comment!!!
If you use:
rand() / (span + 1);
then in order to get values between 0 and 100, then the output values from rand would indeed have to be between 0 and (100 * 100), and this nature would have to be guaranteed. This is because of simple division. A value of 1 will essentially pop out when rand() produces a 101 - 201, a 2 will pop out of the division when the rand() outputs a value of 202 - 302, etc...
In this case, you may be able to get away with it at 100 * 100 is only 10000, and there are definitely integers larger than this in the 32 bit space, but in general doing a divide will not allow you to take advantage utilizing the full number space provided!!!

There are a number of problems with rand(). You've run into one of them, which is that the first several values aren't "random". If you must use rand(), it is always a good idea to discard the first four or results from rand().
srand (time(0));
rand();
rand();
rand();
rand();
Another problem with rand() is that the low order bits are notoriously non-random, even after the above hack. On some systems, the lowest order bit alternates 0,1,0,1,0,1,... It's always better to use the high order bits such as by using the quotient rather than the remainder.
Other problems: Non-randomness (most implementations of rand() fails a number of tests of randomness) and short cycle. With all these problems, the best advice is to use anything but rand().

First, rand() / RAND_MAX does not give a number between 0 and 1, it returns 0. This is because RAND_MAX fits 0 times in the result of rand(). Both are integers, so with integer division it does not return a floating point number.
Second, RAND_MAX may well be the same size as an INT. Multiplying RAND_MAX with anything will then give an overflow.

Related

Why is rand() giving me negative numbers?

I'm trying to make it so that rand_draw holds a random positive number between 0-8. But this code keeps giving negative numbers on some iterations. What's happening?
srand(time(0));
int draw_count = 8;
int rand_draw = (2 * rand()) % draw_count;
cout << rand_draw << endl;
According to cppreference, rand():
Returns a pseudo-random integral value between ​0​ and RAND_MAX (0 and RAND_MAX included).
The value of RAND_MAX is implementation defined, but may very well be the maximum value that can be represented in an int. By doubling the value you get from rand(), the result may overflow into a negative number. This is actually undefined behavior.
I see no reason to double the return value of rand(). You could correct this quite simply:
int rand_draw = rand() % (draw_count + 1);
This will give you random values between 0 and 8, as you specified.
But in modern C++, using the uniform_int_distribution from the C++ Standard Library is a much better way to go. Here's the example from the linked page, modified to show the range you specified:
#include <random>
#include <iostream>
int main()
{
std::random_device rd; //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<> distrib(0, 8);
for (int n=0; n<10; ++n)
//Use `distrib` to transform the random unsigned int generated by gen into an int in [0, 8]
std::cout << distrib(gen) << ' ';
std::cout << '\n';
}
rand() function will generates a random number in this range [0, RAND_MAX).
RAND_MAX is a large number.
More details are discussed in this link
When you use 2*rand(), basically you are shifting the generated number 1 bit to the left. If the generated number is large enough that its second bit from the left side is 1, then after shifting to the left you are generating a negative number.
Here is an example:
Let's assume the generated number in hexadecimal is 0x70000011.
The four most significant bits of this number are 0111, after shifting 1 bit to left, you can see the sign bit is changing.
then you try to use the % operation which results in negative number.
rand() % draw_count -> generates number [0, draw_count)
(rand() % draw_count) + draw_count -> generates number [draw_count, 2* draw_count)
rand() % (2draw_count) -> generates number [0, 2 draw_count)
I figured out a solution, given that I can only use the rand() function. I simply added an if-statement afterwards to check if it's even, and if so keep the variable set to rand_draw, and if not, increment by 1.
int rand_draw = rand() % draw_count;
if (rand_draw % 2 == 0)
{
rand_draw = rand_draw;
}
else
{
rand_draw += 1;
}

Does long double round the number when it gets so small?

I'm on Manjaro 64 bit, latest edition. HP pavilion g6, Codeblocks
Release 13.12 rev 9501 (2013-12-25 18:25:45) gcc 5.2.0 Linux/unicode - 64 bit.
There was a discussion between students on why
sn = 1/n diverges
sn = 1/n^2 converges
So decided to write a program about it, just to show them what kind of output they can expect
#include <iostream>
#include <math.h>
#include <fstream>
using namespace std;
int main()
{
long double sn =0, sn2=0; // sn2 is 1/n^2
ofstream myfile;
myfile.open("/home/Projects/c++/test/test.csv");
for (double n =2; n<100000000;n++){
sn += 1/n;
sn2 += 1/pow(n,2);
myfile << "For n = " << n << " Sn = " << sn << " and Sn2 = " << sn2 << endl;
}
myfile.close();
return 0;
}
Starting from n=9944 I got sn2 = 0.644834, and kept getting it forever. I did expect that the compiler would round the number and ignore the 0s at some point, but this is just too early, no?
So at what theoretical point does 0s start to be ignored? And what to do if you care about all 0s in a number? If long double doesn't do it, then what does?
I know it seems like a silly question but I expected to see a longer number, since you can store big part of pi in long doubles. By the way same result for double too.
The code that you wrote suffers from a classic programming mistake: it sums a sequence of floating-point numbers by adding larger numbers to the sum first and smaller numbers later.
This will inevitably lead to precision loss during addition, since at some point in the sequence the sum will become relatively large, while the next member of the sequence will become relatively small. Adding a sufficiently small floating-point value to a sufficiently large floating-point sum does not affect the sum. Once you reach that point, it will look as if the addition operation is "ignored", even though the value you attempt to add is not zero.
You can observe the same effect if you try calculating 100000000.0f + 1 on a typical machine: it still evaluates to 100000000. This does not happen because 1 somehow gets rounded to zero. This happens because the mathematically-correct result 100000001 is rounded back to 100000000. In order to force 100000000.0f to change through addition, you need to add at least 5 (and the result will be "snapped" to 100000008).
So, the issue here is not that the compiler "rounds the number when it gets so small", as you seem to believe. Your 1/pow(n,2) number is probably fine and sufficiently precise (not rounded to 0). The issue here is that at some iteration of your cycle the small non-zero value of 1/pow(n,2) just cannot affect the sum anymore.
While it is true that adjusting output precision will help you to see better what is going on (as stated in the comments), the real issue is what is described above.
When calculating sums of floating-point sequences with large differences in member magnitudes, you should do it by adding smaller members of the sequence first. Using my 100000000.0f example again, you can easily see that 4.0f + 4.0f + 100000000.0f correctly produces 100000008, while 100000000.0f + 4.0f + 4.0f is still 100000000.
You're not running into precision issues here. The sum doesn't stop at 0.644834; it keeps going to roughly the correct value:
#include <iostream>
#include <math.h>
using namespace std;
int main() {
long double d = 0;
for (double n = 2; n < 100000000; n++) {
d += 1/pow(n, 2);
}
std::cout << d << endl;
return 0;
}
Result:
0.644934
Note the 9! That's not 0.644834 any more.
If you were expecting 1.644934, you should have started the sum at n=1. If you were expecting visible changes between successive partial sums, you didn't see those because C++ is truncating the representation of the sums to 6 significant digits. You can configure your output stream to display more digits with std::setprecision from the iomanip header:
myfile << std::setprecision(9);

Trying to take 1 random digit at a time

I am new to cpp programing, and new to stackoverflow.
I have a simple situation and a problem that is taking more time than reasonable to solve, so I thought I'd ask it here.
I want to take one digit from a rand() at a time. I have managed to strip of the digit, but I can't convert it to an int which I need because it's used as an array index.
Can anyone help? I'd be appreciative.
Also if anyone has a good solution to get evenly-distributed-in-base-10 random numbers, I'd like that too... of course with a rand max that isn't all 9s we don't have that.
KTM
Well you can use the modulus operator to get the digit of what number rand returns.
int digit = rand()%10;
As for your first question, if you have a character digit you can subtract the value of '0' to get the digit.
int digit = char_digit - '0';
If one wants a pedantic even distribution of 0 to 9 one could
Assume rand() itself is evenly distributed. (Not always a good assumption.)
Call rand() again as needed.
int ran10(void) {
const static int r10max = RAND_MAX - (RAND_MAX % 10);
int r;
while ((r = rand()) >= r10max);
return r%10;
}
Example:
If RAMD_MAX was 32767, r10max would have the value of 32760. Any rand value in the range 32760 to 32767 would get tossed and a new random value would be fetched.
While not as fast as modulo-arithmetic implementations like rand() % 10, this will return evenly distributed integers and avoid perodicity in the least significant bits that occur in some pseudo-random number generators (see http://www.gnu.org/software/gsl/manual/html_node/Other-random-number-generators.html).
int rand_integer(int exclusive_upperbound)
{
return int((double)exclusive_upperbound*rand()/RAND_MAX);
}

Extend rand() max range

I created a test application that generates 10k random numbers in a range from 0 to 250 000. Then I calculated MAX and min values and noticed that the MAX value is always around 32k...
Do you have any idea how to extend the possible range? I need a range with MAX value around 250 000!
This is according to the definition of rand(), see:
http://cplusplus.com/reference/clibrary/cstdlib/rand/
http://cplusplus.com/reference/clibrary/cstdlib/RAND_MAX/
If you need larger random numbers, you can use an external library (for example http://www.boost.org/doc/libs/1_49_0/doc/html/boost_random.html) or calculate large random numbers out of multiple small random numbers by yourself.
But pay attention to the distribution you want to get. If you just sum up the small random numbers, the result will not be equally distributed.
If you just scale one small random number by a constant factor, there will be gaps between the possible values.
Taking the product of random numbers also doesn't work.
A possible solution is the following:
1) Take two random numbers a,b
2) Calculate a*(RAND_MAX+1)+b
So you get equally distributed random values up to (RAND_MAX+1)^2-1
Presumably, you also want an equal distribution over this extended
range. About the only way you can effectively do this is to generate a
sequence of smaller numbers, and scale them as if you were working in a
different base. For example, for 250000, you might 4 random numbers
in the range [0,10) and one in range [0,25), along the lines:
int
random250000()
{
return randomInt(10) + 10 * randomInt(10)
+ 100 * randomInt(10) + 1000 * randomInt(10)
+ 10000 * randomInt(25);
}
For this to work, your random number generator must be good; many
implementations of rand() aren't (or at least weren't—I've not
verified the situation recently). You'll also want to eliminate the
bias you get when you map RAND_MAX + 1 different values into 10 or
25 different values. Unless RAND_MAX + 1 is an exact multiple of
10 and 25 (e.g. is an exact multiple of 50), you'll need something
like:
int
randomInt( int upperLimit )
{
int const limit = (RAND_MAX + 1) - (RAND_MAX + 1) % upperLimit;
int result = rand();
while ( result >= limit ) {
result = rand();
return result % upperLimit;
}
(Attention when doing this: there are some machines where RAND_MAX + 1
will overflow; if portability is an issue, you'll need to take
additional precautions.)
All of this, of course, supposes a good quality generator, which is far
from a given.
You can just manipulate your number bitwise by generating smaller random numbers.
For instance, if you need a 32-bit random number:
int32 x = 0;
for (int i = 0; i < 4; ++i) { // 4 == 32/8
int8 tmp = 8bit_random_number_generator();
x <<= 8*i; x |= tmp;
}
If you don't need good randomness in your numbers, you can just use rand() & 0xff for the 8-bit random number generator. Otherwise, something better will be necessary.
Are you using short ints? If so, you will see 32,767 as your max number because anything larger will overflow the short int.
Scale your numbers up by N / RAND_MAX, where N is your desired maximum. If the numbers fit, you can do something like this:
unsigned long long int r = rand() * N / RAND_MAX;
Obviously if the initial part overflows you can't do this, but with N = 250000 you should be fine. RAND_MAX is 32K on many popular platforms.
More generally, to get a random number uniformly in the interval [A, B], use:
A + rand() * (B - A) / RAND_MAX;
Of course you should probably use the proper C++-style <random> library; search this site for many similar questions explaining how to use it.
Edit: In the hope of preventing an escalation of comments, here's yet another copy/paste of the Proper C++ solution for truly uniform distribution on an interval [A, B]:
#include <random>
typedef std::mt19937 rng_type;
typedef unsigned long int int_type; // anything you like
std::uniform_int_distribution<int_type> udist(A, B);
rng_type rng;
int main()
{
// seed rng first:
rng_type::result_type const seedval = get_seed();
rng.seed(seedval);
int_type random_number = udist(rng);
// use random_number
}
Don't forget to seend the RNG! If you store the seed value, you can replay the same random sequence later on.

C++ generating random numbers

My output is 20 random 1's, not between 10 and 1, can anyone explain why this is happening?
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
srand((unsigned)time(0));
int random_integer;
int lowest=1, highest=10;
int range=(highest-lowest)+1;
for(int index=0; index<20; index++){
random_integer = lowest+int(range*rand()/(RAND_MAX + 1.0));
cout << random_integer << endl;
}
}
output:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
Because, on your platform, RAND_MAX == INT_MAX.
The expression range*rand() can never take on a value greater than INT_MAX. If the mathematical expression is greater than INT_MAX, then integer overflow reduces it to a number between INT_MIN and INT_MAX. Dividing that by RAND_MAX will always yield zero.
Try this expression:
random_integer = lowest+int(range*(rand()/(RAND_MAX + 1.0)))
It's much easier to use the <random> library correctly than rand (assuming you're familiar enough with C++ that the syntax doesn't throw you).
#include <random>
#include <iostream>
int main() {
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 eng(seed);
std::uniform_int_distribution<> dist(1, 10);
for(int i = 0; i < 20; ++i)
std::cout << dist(eng) << " ";
}
random_integer = (rand() % 10) + 1
That should give you a pseudo-random number between 1 & 10.
A somewhat late answer, but it should provide some additional
information if the quality of the generation is important. (Not all
applications need this—a slight bias is often not a problem.)
First, of course, the problem in the original code is the fact that
range * rand() has precedence over the following division, and is done
using integer arithmetic. Depending on RAND_MAX, this can easily
result in overflow, with implementation defined results; on all
implementations that I know, if it does result in overflow (because
RAND_MAX > INT_MAX / range, the actual results will almost certainly
be smaller than RAND_MAX + 1.0, and the division will result in a
value less than 1.0. There are several ways of avoiding this: the
simplest and most reliable is simply rand() % range + lowest.
Note that this supposes that rand() is of reasonable quality. Many
earlier implementations weren't, and I've seen at least one where
rand() % 6 + 1 to simulate a dice throw alternated odd and even. The
only correct solution here is to get a better implementation of
rand(); it has lead to people trying alternative solutions, such as
(range * (rand() / (RAND_MAX + 1.0))) + lowest. This masks the
problem, but it won't change a bad generator into a good one.
A second issue, if the quality of the generation is important, is
that when generating random integers, you're discretizing: if you're
simulating the throw of a die, for example, you have six possible
values, which you want to occur with equal probability. The random
generator will generate RAND_MAX + 1 different values, with equal
probability. If RAND_MAX + 1 is not a multiple of 6, there's no
possible way of distributing the values equaly amont the 6 desired
values. Imagine the simple case where RAND_MAX + 1 is 10. Using the
% method above, the values 1–4 are twice as likely as the the
values 5 and 6. If you use the more complicated formula 1 + int(6 *
(rand() / (RAND_MAX + 1.0))) (in the case where RAND_MAX + 1 == 10,
it turns out that 3 and 6 are only half as likely as the other values.
Mathematically, there's simply no way of distributing 10 different
values into 6 slots with an equal number of elements in each slot.
Of course, RAND_MAX will always be considerably larger than 10, and
the bias introduced will be considerably less; if the range is
significantly less than RAND_MAX, it could be acceptable. If it's
not, however, the usual procedure is something like:
int limit = (RAND_MAX + 1LL) - (RAND_MAX + 1LL) % range;
// 1LL will prevent overflow on most machines.
int result = rand();
while ( result >= limit ) {
result = rand();
}
return result % range + lowest;
(There are several ways of determining the values to throw out. This
happens to be the one I use, but I remember Andy Koenig using something
completely different—but which resulted in the same values being
thrown out in the end.)
Note that most of the time, you won't enter the loop; the worst case is
when range is (RAND_MAX + 1) / 2 + 1, in which case, you'll still
average just under one time through the loop.
Note that these comments only apply when you need a fixed number of
discrete results. For the (other) common case of generating a random
floating point number in the range of [0,1), rand() / (RAND_MAX +
1.0) is about as good as you're going to get.
Visual studio 2008 has no trouble with that program at all and happily generates a swathe of random numbers.
What I would be careful of is the /(RAND_MAX +1.0) as this will likely fall foul of integer problems and end up with a big fat zero.
Cast to double before dividing and then cast back to int afterwards
I suggest you replace rand()/(RAND_MAX + 1.0) with range*double(rand())/(RAND_MAX + 1.0)). Since my solution seems to give headaches ...
possible combinations of arguments:
range*rand() is an integer and overflows.
double(range*rand()) overflows before you convert it to double.
range*double(rand()) is not overflowing and yields expected results.
My original post had two braces but they did not change anything (results are the same).
(rand() % highest) + lowest + 1
Probably "10 * rand()" is smaller than "RAND_MAX + 1.0", so the value of your calculation is 0.
You are generating a random number (ie (range*rand()/(RAND_MAX + 1.0))) whose value is between -1 and 1 (]-1,1[) and then casting it to an integer. The integer value of such number is always 0 so you end up with the lower + 0
EDIT: added the formula to make my answer clearer
What about using a condition to check if the last number is the same as the current one? If the condition is met then generate another random number. This solution works but it will take more time though.
It is one of the simplest logics, got it from a blog. in this logic you can limit the random numbers with that given modulus(%) operator inside the for loop, its just a copy and paste from that blog, but any way check it out:
// random numbers generation in C++ using builtin functions
#include <iostream>
using namespace std;
#include <iomanip>
using std::setw;
#include <cstdlib> // contains function prototype for rand
int main()
{
// loop 20 times
for ( int counter = 1; counter <= 20; counter++ ) {
// pick random number from 1 to 6 and output it
cout << setw( 10 ) << ( 1 + rand() % 6 );
// if counter divisible by 5, begin new line of output
if ( counter % 5 == 0 )
cout << endl;
}
return 0; // indicates successful termination
} // end main
- See more at: http://www.programmingtunes.com/generation-of-random-numbers-c/#sthash.BTZoT5ot.dpuf