Issue with Random Number Generator in a Class [duplicate] - c++

This question already has answers here:
srand() — why call it only once?
(7 answers)
Closed 9 years ago.
First off this could be complete rubbish as I am new to C++ classes and have never used a random number generator before. But this is my attempt. It generates a random number between the values that I want, thats fine. but when outputting them via an array, all the random values are the same.
RandomNumberGenerator.h
#pragma once
#include <iostream>
#include <cstdlib>
#include <ctime>
class RandomNumber
{
public:
void randomNumber();
int actualRandomNumber;
};
RandomNumberGenerator.cpp
#include "RandomNumberGenerator.h"
void RandomNumber::randomNumber()
{
srand (time(NULL));
actualRandomNumber = rand() % 66 + 1;
}
Game.h
#include "RandomNumberGenerator.h"
class Game
{
private:
int myNumbers[6];
public:
void createGame();
};
Game.cpp
#include "Game.h"
void Game::createGame()
{
RandomNumber create;
std::cout << "Welcome to your game!" << std::endl;
for (int i = 0; i < 6; i++)
{
create.randomNumber();
myNumbers[i] = create.actualRandomNumber;
}
for (int i = 0; i < 6; i++)
{
std::cout << myNumbers[i] << std::endl;
}
}
main
#include "Game.h"
#include "RandomNumberGenerator.h"
int main()
{
Game play;
play.createGame();
system("pause");
return 0;
}
Thanks in advance for anyones time.

Everytime you call srand(time(NULL)), you set the starting point of your sequence depending on a value that only changes once a second, thus your number only changes once a second (independend from number of calls).
So only calling srand() once will fix your code.
Notice, that both rand() and your actualRandomNumber = rand() % 66 + 1; are really bad regarding their "randomness" (why).
Use the C++ STL instead, consider the example on the bottom of the page (you want the uniform int distribution).
Edit: Typo and link to OneC++ Talk

The pseudo random number generator starts with a certain number and then generates a sequence based on the first number.
When the first number is the same the output sequence will be the same.
To generate different sequences each time you launch your program, the idea is to use the starting time of your program relatively to a specific date in miliseconds.
So the Error in your code is that you placed the srand(time(NULL)) in the function randomnumber() and it's being called in the loop. Because the CPU is so fast the time(NULL) (the first number in the sequence) will return the same value in miliseconds. Thus your having the same sequence.
To solve this place srand(time(NULL)) in main()

Related

Trying to stick randomly generated numbers into an array

I'm working on a project currently that involves taking randomly generated numbers, putting them into an array, then using that array throughout the entire program. It's basically supposed to be a number version of wordle. What I'm stuck on right now it trying to make the function to array connection work, and I don't know what I'm doing wrong.
I'm in a beginner course for programming, so I'm probably making a lot of dumb mistakes. The purpose of the function is to generate 5 random numbers between 0 and 9. The I'm supposed to take those numbers and stick then into an array. Then the array needs to be saved so it can be used for a game.
#include <iostream>
#include <random>
#include <chrono>
#include <array>
using namespace std;
//using std::array;
int getRandomDigit() {
std::random_device randomSource;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine engine(seed);
std::uniform_int_distribution<int> uniformDist(0,9);
//for (int i = 0; i < 5; i++) {
int digits[5] = {getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit()};
return digits[5];
}
//for (int i = 0; i < 5; i++) {
//int randArray[5] = {getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit()};
int main()
{
//for (int i = 0; i < 5; i++) {
//int randArray[5] = {getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit()};
//}
cout << digits[1] <<endl;
return 0;
}
This is what I have so far. I compile it, and it gives me an error of "'digits' was not declared in this scope". I'm honestly very lost on how to make this work. The random number generator was given to us by our instructor
Your compilation error "'digits' was not declared in this scope" is because you are using digits in your main function without declaring it first. You only have it declared in getRandomDigit(). Declare your array in main() instead and set it to values that are returned from getRandomDigit(). Additionally, you can not return an array in C++ directly. Focus on returning a single int from the getRandomDigit() function and populating your array in main().

Generating two ( or multiple) uniformly distributed random numbers c++ [duplicate]

This question already has answers here:
Why does rand() return the same value using srand(time(null)) in this for loop?
(5 answers)
Closed 7 years ago.
I would like to generate several uniformly distributed random numbers in the same pass.
So far I have a "standard" function for generating a random number
double generateRandomNumber()
{
srand((unsigned)time(NULL));
double r=((double)rand()/(double)RAND_MAX);
return r;
}
how ever when in main I call it like that:
# include <iostream>
# include <string>
# include <cmath>
# include <ctime>
int main()
{
// generate random number
double rr1=generateRandomNumber();
double rr2=generateRandomNumber();
cout << rr1 << endl;
cout << rr2 << endl;
return 0;
}
I get that both numbers are the same ( I guess its the time limitations of seconds), anyways, this is something I would like to generelize to multiple random numbers.
Can anyone suggest a better way? maybe using a different method or library?
Do not call srand every time beore using rand.
srand should be call only once on the program begins.
You can use static variable to see if srand is previously called.
double generateRandomNumber()
{
static bool initialized = false;
if (!initialized)
{
srand((unsigned)time(NULL));
initialized = true;
}
double r=((double)rand()/(double)RAND_MAX);
return r;
}

Generating a random double between a range of values

Im currently having trouble generating random numbers between -32.768 and 32.768. It keeps giving me the same values but with a small change in the decimal field. ex : 27.xxx.
Heres my code, any help would be appreciated.
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
srand( time(NULL) );
double r = (68.556*rand()/RAND_MAX - 32.768);
cout << r << endl;
return 0;
}
I should mention if you're using a C++11 compiler, you can use something like this, which is actually easier to read and harder to mess up:
#include <random>
#include <iostream>
#include <ctime>
int main()
{
//Type of random number distribution
std::uniform_real_distribution<double> dist(-32.768, 32.768); //(min, max)
//Mersenne Twister: Good quality random number generator
std::mt19937 rng;
//Initialize with non-deterministic seeds
rng.seed(std::random_device{}());
// generate 10 random numbers.
for (int i=0; i<10; i++)
{
std::cout << dist(rng) << std::endl;
}
return 0;
}
As bames53 pointed out, the above code can be made even shorter if you make full use of c++11:
#include <random>
#include <iostream>
#include <ctime>
#include <algorithm>
#include <iterator>
int main()
{
std::mt19937 rng;
std::uniform_real_distribution<double> dist(-32.768, 32.768); //(min, max)
rng.seed(std::random_device{}()); //non-deterministic seed
std::generate_n(
std::ostream_iterator<double>(std::cout, "\n"),
10,
[&]{ return dist(rng);} );
return 0;
}
Also, If you are not using c++ 11 you can use the following function instead:
double randDouble(double precision, double lowerBound, double upperBound) {
double random;
random = static_cast<double>(((rand()%(static_cast<int>(std::pow(10,precision)*(upperBound - lowerBound) + 1))) + lowerBound*std::pow(10,precision)))/std::pow(10,precision);
return random;
}
So, I think this is a typical case of "using time(NULL) isn't a great way of seeding random numbers for runs that start close together". There isn't that many bits that change in time(NULL) from one call to the next, so random numbers are fairly similar. This is not a new phenomena - if you google "my random numbers aren't very random", you'll find LOTS of this.
There are a few different solutions - getting a microsecond or nanosecond time would be the simplest choice - in Linux gettimeofday will give you a microsecond time as part of the struct.
It seams to be plainly obvious but some of the examples say otherwise... but i thought when you divide 1 int with another you always get an int? and you need to type cast each int to double/float before you divide them.
ie: double r = (68.556* (double)rand()/(double)RAND_MAX - 32.768);
also if you call srand() every time you call rand() you reset the seed which results in similar values returned every time instead of ''random'' ones.
I've added a for loop to your program:
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main () {
srand(time (NULL));
for (int i = 0; i < 10; ++i) {
double r = ((68.556 * rand () / RAND_MAX) - 32.768);
cout << r << endl;
}
return 0;
}
Example output:
31.6779
-28.2096
31.5672
18.9916
-1.57149
-0.993889
-32.4737
24.6982
25.936
26.4152
It seems Okay to me. I've added the code on Ideone for you.
Here are four runs:
Run 1:
-29.0863
-22.3973
34.1034
-1.41155
-2.60232
-30.5257
31.9254
-17.0673
31.7522
28.227
Run 2:
-14.2872
-0.185124
-27.3674
8.12921
22.4611
-0.414546
-21.4944
-11.0871
4.87673
5.4545
Run 3:
-23.9083
-6.04738
-6.54314
30.1767
-16.2224
-19.4619
3.37444
9.28014
25.9318
-22.8807
Run 4:
25.1364
16.3011
0.596151
5.3953
-25.2851
10.7301
18.4541
-18.8511
-0.828694
22.8335
Perhaps you're not waiting at least a second between runs?

Can I make my do while loop create a new random number every time it loops?

Can I make my do while loop create a new number from my pseudo random number every time the loop comes around again? If so, how?'
EDIT: Sorry, it's in C++
EDIT2: I just want a new number between 0 and 3 (0,1,2,3) every time the do...while loop goes around for an integer
While you might like the following example:
do
{
new_number = out_of(my_pseudo_random_number);
}
while(true);
You may find it more useful:
int main()
{
srand(time(NULL)); // Initialize once at program startup.
do
{
int number = rand(); // generate new random number,
}
while(true);
}
(But I'm absolutely not sure what your're asking for)
This will specifically make random numbers from 0 t0 3.
You don't necessarily need the iostream/cout statements except for the output I do.
rand() % 4; creates a random number from 0 to (not including) 4.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main()
{
int num;
//initialize random seed
srand(time(NULL));
//make some numbers
do{
num = rand() % 4;
cout << num;
} while(true);
return 0;
}

What's wrong with my random number generator?

I'm just diving into some C++ and I decided to make a random number generator (how random the number is, it really doesn't matter). Most of the code is copied off then net but my newbie eyes cannot see anything wrong with this, is there any way this can be tweaked to give a number other than "6" each time?
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int random_number(int min, int max)
{
srand((unsigned)time(0));
int random_num;
int range=(max-min)+1;
random_num = min+int(range*rand()/(RAND_MAX + 1.0));
return random_num;
}
int main()
{
for(int i =0;i < 100;i++)
{
cout << random_number(3,10) << endl;
}
}
Add srand before the loop
srand((unsigned)time(0));
for(int i =0;i < 100;i++)
{
std::cout << random_number(3,10) << endl;
}
Don't call srand() within random_number(). This will re-seed the random number generator every call. For 100 calls, you'll very likely get the same seed every call, and therefore the same number.
The problem is that you use srand everytime. CPU is so fast that it will execute all this code in a single second, so you get the same seed each time.
Move srand out of the loop, call it only once.