Does using a modulus with rand() limit results? - c++

This is a program created for a game, in which I am using rand() to try and generate randomly what types of trees can be found at a settlement. The seed for rand() has been set to time in main.cpp so that it is unique each time. My question here however is about my modulus: trees[x]=rand()%40;
If I understand how rand() works correctly, once it outputs a number it has already outputted, it will repeat the same number sequence it has already because it uses a formula. Is using the modulus limiting my program to only produce 40 different random number sequences? Or does it continue to draw the new random number for each of the following arrays from the system clock?
#include <stdafx.h>
#include <iostream>
#include <cstdlib> // for rand() and srand()
#include <ctime> // for time()
using namespace std;
int forestdeterminator()
{
int trees[32];
for (int x=0; x<32; ++x)
trees[x]=rand()%40;
if (trees[0]>=1 && trees[0]<=9)
cout << "Birch Trees" << endl;
if (trees[1]>=1 && trees[1]<=3)
cout << "Mahogany Trees" << endl;
if (trees[2]>=1 && trees[2]<=20)
cout << "Oak Trees" << endl;
if (trees[3]>=1 && trees[3]<=4)
cout << "Cherry Trees" << endl;
if (trees[4]==1)
cout << "Tigerwood Trees" << endl;
if (trees[5]==1)
cout << "Swampwood Trees (Swamp Only)" << endl;
if (trees[6]>=1 && trees[6]<=8)
cout << "Yew Trees" << endl;
if (trees[7]==1)
cout << "Petrified Trees" << endl;
if (trees[8]>=1 && trees[8]<=24)
cout << "Pine Trees" << endl;
if etc etc...

No. You are only using the result of the rand() function, so it has absolutely no effect on the output of the PRNG. Only if you used rand()%40 to successively seed the PRNG would you run into that limit.
Also, note that a PRNG is typically only seeded from the system clock once, at its initialization. From there on, each number "depends" on the previously outputted one.
Finally, be aware that using a modulus on the output of a PRNG will in almost all cases skew the resulting probability distribution. This effect is very very small, for small modulus, but may be important to consider, depending on your application.

Is using the modulus limiting my program to only produce 40 different random number sequences?
Sequences, debatable. Numbers. Definitely. You can't have effective randomness with only 40 possible outputs; there's just not enough freedom there to fluctuate. But no, you're not effecting the numbers that are outputted, you're just heavily limiting what the output of your program is.

what you do is put 32 (pseudo)randomly generated integers in range from 0 to 39 to an array called trees. doing this doesn't affect how the function rand() works. it'll keep generating numbers from the full scope, no matter what operations you apply to it's former results.
so, if I understand you, the answer is: no, using rand()%40 somewhere in your code won't magically make the rand() function generate only numbers from range 0-39.

Related

How do I use the rand functions output in C++?

I am trying to create a slot machine where I have to generate 3 random numbers from 2 - 7 and then use that output to give different outcomes. For example if the output is 777 and then your bet gets multiplied by 10, if it's 222 then it gets multiplied by 5. I can't seem to get the output of the rand function into a variable to use it and its not calculating properly.
Code:
This is not the full code
if (bet <= 2000)
{
std::cout << endl;
int game_num = 0;
srand (0);
for (int i = 0; i < 3; i++)
std::cout << (rand() % 1) + 2;
std::cout << endl;
if (game_num == 777)
{
bet = bet * 10;
std::cout << "You Won: " << bet << endl;
return 0;
}
else if (game_num == 222 || 333 || 444 || 555 || 666)
{
bet = bet * 5;
std::cout << "You Won: " << bet << endl;
return 0;
}
The issue is that you aren’t seeding the random number generator properly in this situation.
This will always return the same sequence of random numbers every time the program runs.
srand(0)
You want to seed the random number generator with a new value each time the program is run.
Using the timestamp at runtime will enable that behavior.
srand(time(0))
Dan's answer is correct, you're using the same seed every time, so every sequence of numbers is identical. You need to seed with a random value. Time as source of randomness isn't great in terms of being random, but it's working unless you run twice in the same second (due to time() only counting seconds, and seconds being ... long for modern computers, unlike 1970's computers, when that way of seeding was invented).
So, instead, honestly, don't use srand or rand at all. They're really bad random number generators to begin with, and their dependence on "hidden" state makes them a nightmare to deal with. Simply. Ignore their existence!
C++ brings its own random facilities:
You want a uniform integer distribution, so use uniform_int_distribution. Seed with an actual random value from actual randomness-generating events.
#include <random>
// …
// Somewhen before you need the random numbers, not every time:
// Will be used to obtain a seed for the random number engine
std::random_device real_random;
// Set up the generator for random bits, seed it from the actual random
std::mt19937 gen(real_random());
// Use that to generate random numbers in [2,7]
std::uniform_int_distribution<> distrib(2, 7);
// Where you need the randomness:
for (int i = 0; i < 3; i++)
std::cout << distrib(gen) << "\n";

How do I "surpass" the int function of C++

Alright so, I'm a noob first of all. I started studying code (in C++), and I want to make a random number generator. It's great and all, but as far as I've observed, the generated numbers never exceed the "int" limit of 32768, even tho my variables are all "unsigned long long" (I'm pretty sure that's how you get the largest pool of numbers). I'm pretty sure it's something small, but it;s been bothering me for a day, and I really need answers.
Here's how my current code looks like :
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
unsigned long long n,m,r,mx;
cout<< "Please Enter The Number Of Desired Randomly Generated Numbers : ";
cin>>m;
cout<< "Please Enter An Upper Limit to the Random Numbers : " ;
cin>>mx;
srand ( time(NULL) );
for (int i=1; i<=m ; i++)
{
n = rand() % mx;
cout << n << endl;
}
cout<< "Rate this Program Out Of 10: ";
cin >> r;
cout << r << " " << "/" << "10";
return 0;
}
Even though all the numbers you use are unsigned long long, rand() will only ever return a number less than or equal to RAND_MAX which is guaranteed to be 32767 or more.
To guarantee a return value more than 32767 you're going to need some more advanced random number generation techniques. The standard library has a module for this called random.
Take a look at the uniform_int_distribution object. That page gives an example of how to use it to generate regular integers however the object does take a template parameter that allows you to specify what kind of integer is returned.
In your case you would want to use:
std::uniform_int_distribution<unsigned long long>
Using that in the example on the page will generate 10 unsigned long long numbers (however if you copy the example exactly they will still be limited to between 1 and 6).

Program will not output data to console when using a data input size greater than 30 million

I'm trying to make a program that will eventually show the runtime differences with large data inputs by using a binary search tree and a vector. But before I get to that, I'm testing to see if the insertion and search functions are working properly. It seems to be fine but whenever I assign SIZE to be 30 million or more, after about 10-20 seconds, it will only display Press any key to continue... with no output. However if I assign SIZE to equal to 20 million or less, it will output the search results as I programmed it. So what do you think is causing this problem?
Some side notes:
I'm storing a unique, (no duplicates) randomly generated value into the tree as well as the vector. So at the end, the tree and the vector will both have the exact same values. When the program runs the search portion, if a value is found in the BST, then it should be found in the vector as well. So far this has worked with no problems when using 20 million values or less.
Also, I'm using randValue = rand() * rand(); to generate the random values because I know the maximum value of rand() is 32767. So multiplying it by itself will guarantee a range of numbers from 0 - 1,073,741,824. I know the insertion and searching methods I'm using are inefficient because I'm making sure there are no duplicates but it's not my concern right now. This is just for my own practice.
I'm only posting up my main.cpp for the sake of simplicity. If you think the problem lies in one of my other files, I'll post the rest up.
Here's my main.cpp:
#include <iostream>
#include <time.h>
#include <vector>
#include "BSTTemplate.h"
#include "functions.h"
using namespace std;
int main()
{
const long long SIZE = 30000000;
vector<long long> vector1(SIZE);
long long randNum;
binarySearchTree<long long> bst1;
srand(time(NULL));
//inserts data into BST and into the vector AND makes sure there are no duplicates
for(long long i = 0; i < SIZE; i++)
{
randNum = randLLNum();
bst1.insert(randNum);
if(bst1.numDups == 1)//if the random number generated is duplicated, don't count it and redo that iteration
{
i--;
bst1.numDups = 0;
continue;
}
vector1[i] = randNum;
}
//search for a random value in both the BST and the vector
for(int i = 0; i < 5; i++)
{
randNum = randLLNum();
cout << endl << "The random number chosen is: " << randNum << endl << endl;
//searching with BST
cout << "Searching for " << randNum << " in BST..." << endl;
if(bst1.search(randNum))
cout << randNum << " = found" << endl;
else
cout << randNum << " = not found" << endl;
//searching with linear search using vectors
cout << endl << "Searching for " << randNum << " in vector..." << endl;
if(containsInVector(vector1, SIZE, randNum))
cout << randNum << " = found" << endl;
else
cout << randNum << " = not found" << endl;
}
cout << endl;
return 0;
}
(Comments reposted as answer at OP's request)
Options include: compile 64 bit (if you're not already - may make it better or worse depending on whether RAM or address space are the issue), buy more memory, adjust your operating system's swap memory settings (letting it use more disk), design a more memory-efficient tree (but at best you'll probably only get an order of magnitude improvement, maybe less, and it could impact other things like performance characteristics), redesign your tree so it manually saves data out to disk and reads it back (e.g. with an LRU).
Here's a how-to for compiling 64 bit on VC++: msdn.microsoft.com/en-us/library/9yb4317s.aspx

Generate random number between 1 and 9 in c++

What do I need to add, so that it will not continuously choose the number as 8 but rather any of the numbers 1 through 9? srand?
int main()
{
int iRand = (rand() % 9+1);
if (iRand==1)
{
cout << "The planet of the day is Mercury!" <<endl;
cout << "Mercury is the closest planet to the sun." <<endl;
}
else if (iRand==2)
{
cout << "The planet of the day is Venus!" <<endl;
cout << "Venus is the hottest planet in our solar system." <<endl;
}
// .... 3..4..5..6..7..8
else
{
cout << "The planet of the day is Pluto!" <<endl;
}
return 0;
}
You need to initialize your random seed first!
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
srand (time(NULL));
Pseudorandom number generators like rand() aren't actually totally random. Instead, the numbers are determined by the generator's initial state, called a seed. Your program, as it exists now, will have the same seed on every execution--and thus the random number will be the same every time.
srand() to the rescue -- it lets you specify the seed.
If you were to specify a constant seed (like srand(2)) then you'd have the same problem as now, just with a different result. Thus, to guarantee differing results every time the program executes, we can initialize the random number generator with the current time -- so as long as you never travel in time, you'll never get the exact same sequence of numbers.
(Note: in a real world applications, this might not be good, because someone could repeat past results by (e.g.) manually resetting the system clock to different times. Which someone did once to steal money from a casino.)

not random enough for monte carlo

I am trying to generate values from a normal distribution using a monte carlo method, as per the website http://math60082.blogspot.ca/2013/03/c-coding-random-numbers-and-monte-carlo.html
I modified the code a bit from the original so it calculates the variance and mean for the numbers generated directly to check if the method is working rather than do the tests separately (same difference really but just a heads up).
Question
Regardless of what I do, the variance is way above 1 and the mean is not zero. Is it possible the pseudo-random numbers generated aren't random enough?
Code
PLEASE NOTE THAT THE AUTHOR OF THE ABOVE GIVEN WEBSITE IS THE PERSON WHO WROTE THE CODE
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <iostream>
using namespace std;
// return a uniformly distributed random number
double uniformRandom()
{
return ( (double)(rand()) + 1. )/( (double)(RAND_MAX) + 1. );
}
// return a normally distributed random number
double normalRandom()
{
double u1=uniformRandom();
double u2=uniformRandom();
return cos(8.*atan(1.)*u2)*sqrt(-2.*log(u1));
}
int main()
{
double z;
int N=1000;
double array[N];
double mean=0 ,variance=0;
srand(time(NULL));
for(int i=0;i<N;i++)
{
z=normalRandom();
cout << i << "->"<< z<< endl;
mean+=z;
array[i]=z;
}
mean=mean/N ;
cout << " mean = " << mean << endl;
for(int i=0;i<N;i++)
{
variance = variance + (mean - array[i])*(mean - array[i]);
}
variance = variance/N;
cout << " variance = " << variance << endl;
return 0;
}
UPDATE
Apparently as pointed by users, I screwed up and the program was not working because of a very silly mistake.
You seems computed the mean in a wrong way. mean should be averaged over N, while you only sum over all array elements. current mean is actually sum.
mean = mean /N
rand() is a very low quality random numbers generator in most implementations. Some Linux versions would take value from kernel entropy pool, but it is not guaranteed across platforms (e.g. on Windows?) Use a Mersenne Twister instead. Boost libraries implement one.
EDIT: taocp answer highlights a coding problem, but the RNG issue still applies.