C++ generate random number every time - c++

I need to make a simulator for a college homework. In this simulator there are 3 computers, 2 of which send messages to computer 1 which then decides to either send the message or reject it. The rejection is random chance with 20% of rejection on computer 2 and 50% on computer 3. I use the rand()%100+1 function with the srand(time(NULL)) seed. It makes a random number however I need to run this multiple times and every time the same random number is used. For example if I run the simulation 12 times and the number generated is 45, 45 is used 12 times. I've both placed the random number generator inside the code and made a function outside.
How can you make a random number generator that generates a random number every time?
#include <iostream>
#include <new>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
using namespace std;
int randomgen()
{
int rndnum=0;
srand (time(NULL));
rndnum=rand()%100+1;
cout<< rndnum<<endl;
return rndnum;
}
struct comp1
{
int rejected=0;
int received=0;
int sent=0;
int onhold=0;
bool comp2reception()
{
received++;
bool result=false;
int rndnum=0;
srand (time(NULL));
rndnum=rand()%100+1;
if(rndnum<=20)
{
rejected++;
result=false;
}
if(rndnum>=21)
{
onhold++;
result=true;
}
return result;
}
bool comp3reception()
{
received++;
bool result=false;
int rndnum=randomgen;
if(rndnum<=50)
{
rejected++;
result=false;
}
if(rndnum>=51)
{
onhold++;
result=true;
}
return result;
}
};

Use the C++11 header <random>.
#include <random>
static std::random_device rd;
static std::mt19937 gen(rd());
int randomgen()
{
std::uniform_int_distribution<> dis(0,100);
int rndnum = dis(gen);
std::cout << rndnum << std::endl;
return rndnum;
}

Call srand(time(NULL)) just once at the beginning of the program.
Since time() return number of seconds from 1970 and you program probably takes less than that to finish, you esentially reset the generator with same value before each call. Which of course returns same (first) value each call.

Related

Generating and printing random numbers using threads in C++

I'm currently working on a project which requires the use of threads. However, before tackling the project, I want to create a simple exercise for myself to test my understanding of threads.
What I have are 2x functions; one for infinitely generating random numbers and the other for printing the output of this function.
The value of this random number will be continuously updated via a pointer.
From my understanding, I will need a mutex to prevent undefined behavior when reading and writing values to this pointer. I would also need to detach the random number generator function from the main function.
However, I'm having issues trying to build the project in Visual Studio Code which I suspecting due to a flaw in my logic.
#include <bits/stdc++.h>
#include <iostream>
#include <thread>
#include <mutex>
std::mutex global_mu;
void generateRandomNum(int min, int max, int *number)
{
while (true) {
global_mu.lock();
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> uni(min, max);
*number = uni(rng);
global_mu.unlock();
}
}
int main()
{
int *int_pointer;
int number = 0;
int_pointer = &number;
std::thread t1(generateRandomNum, 0, 3000, int_pointer);
t1.detach();
while(true) {
global_mu.lock();
std::cout << int_pointer << std::endl;
global_mu.unlock();
}
}
This looks wrong:
std::cout << int_pointer << std::endl;
You're trying to print the value of the pointer instead of printing the value of the int variable to which it points. You either should do this:
std::cout << *int_pointer << std::endl;
or this:
std::cout << number << std::endl;
This also looks like it maybe does not do what you want:
while (true) {
...
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> uni(min, max);
*number = uni(rng);
...
}
You are constructing and initializing a new random number generator for each iteration of the loop. You probably should move the PRNG out of the loop:
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> uni(min, max);
while (true) {
...
*number = uni(rng);
...
}
Finally, you probably should not ever do this:
while(true) {
global_mu.lock();
...
global_mu.unlock();
}
What's the very next thing that the thread does after it calls unlock()? The next thing it does is, it re-locks the same mutex again.
I don't want to get too technical, but the problem in this situation is that the thread that is most likely to acquire the mutex will be the one that just released it, and not the one that's been waiting for a long time. Whichever thread gets in to the mutex first, is going to starve the other thread.
The way out of the starvation problem is to only lock the mutex for the least amount of time necessary. E.g.,:
void generateRandomNum(int min, int max, int *number)
{
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> uni(min, max);
while (true) {
int temp = uni(rng);
global_mu.lock();
*number = temp;
global_mu.unlock();
}
}
int main()
{
int *int_pointer;
int number = 0;
int_pointer = &number;
std::thread t1(generateRandomNum, 0, 3000, int_pointer);
t1.detach();
while(true) {
int temp;
global_mu.lock();
temp = number;
global_mu.unlock();
std::cout << temp << std::endl;
}
}
If this feels like you're writing a lot of extra lines, you're right. Multi-threading is hard to get right. And, in order to get high performance from a multi-threaded program, you are going to have to write extra lines of code, and maybe even make the program do more work per CPU than a single threaded program would do.

random number generator that doesn't repeat it self (cpp/c++)

I want to make a function that generates numbers but doesn't repeat it self. If every number is generated the array can be emptied and it can start over again.
This is the code I made but it doesn't work.
The comments in the code explains the code a little.
The largest number that is allowed is "howManyWords".
This is used to display words which are stored in an array
I want to use it like this: array\[random()\]
#include <stdio.h>
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
//public scope
int howManyWords; // how many words you have enter
int random(){
int random;
int numbers[howManyWords];
srand(time(0)); //changing the algorithm
random = rand() % howManyWords;
numbers[random] = random; // store the digit in the position in the array equal to the digit that is generated
for(int i=0; i<howManyWords; i++){ // going through every element in the array
if(numbers[i] == random){ // if the number is already generated, generate a different number
random = rand() % howManyWords;
}
}
return random;
}
Rather than your function, which discards the state of which numbers it has returned each time it is called, you should use a function object.
struct random_t {
random_t(int max) : values(max), current(max) {
std::iota(values.begin(), values.end(), 0);
}
template<typename URBG = std::random_device &>
int operator()(URBG&& urbg = default_random) {
if (current == values.size()) {
shuffle(std::forward<URBG>(urbg));
}
return values[current++];
}
private:
template<typename URBG>
void shuffle(URBG&& urbg) {
std::shuffle(values.begin(), values.end(), std::forward<URBG>(urbg));
current = 0;
}
std::vector<int> values;
std::vector<int>::size_type current;
static thread_local std::random_device default_random;
};
See it live

No Output from Array Loop

I am to draw 3 balls from an urn of 24 and add up the total discount the balls represent. I am not allowed to replace the balls after drawing, so there can be no duplicate balls drawn. The discounts are 1, 2, 3, 4, 5, 6, 7, 8, and there are 3 of each.
My solution to this problem was to create multiple while loops that roll out of 24 and re-roll until no duplicates are drawn. I have done a loop like this in the past that would loop random numbers until a non-duplicate was chosen and it worked fine, so I set this program up the same way.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int draw(int urn[], int draws[]);
int main()
{
int discountSum,discount;
int urn[24]={1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8};
int draws[1000]={0};
draw(urn,draws);
cin >> discount;
int averageDiscount=discount/1000;
return 0;
}
int draw(int urn[], int draws[])
{
static int discountSum=0;
int i; //simulations counter
int ball1, ball2, ball3;
int score1, score2, score3;
int totalDiscount;
srand(time(0));
for(i=0;i<1000;i++)
{
ball1=rand()%24;
while (ball2==ball1)
{
ball2=rand()%24;
}
while ((ball3==ball2)||(ball3==ball1))
{
ball3=rand()%24;
}
score1=urn[ball1];
score2=urn[ball2];
score3=urn[ball3];
totalDiscount=score1+score2+score3;
draws[i]=totalDiscount;
cout << "1) " << draws[i] << " percent discount.\n";
discountSum+=totalDiscount;
}
return discountSum;
}
When I run this code, instead of receiving an error, the program runs with no output, and a return of a negative garbage value instead of 0. I would like to see the output from each discount up to the 1000th loop.
It looks as if the bug is that ball2 and ball3 are compared before they're ever set to anything. They're never even initialized, which is the likely cause of your "garbage value." It'll probably work if you "draw" each ball before comparing it, as:
ball1=rand()%24;
ball2=rand()%24;
while (ball2==ball1)
{
ball2=rand()%24;
}
ball3=rand()%24;
while ((ball3==ball2)||(ball3==ball1))
{
ball3=rand()%24;
}
An even better way would be to use do...while loops instead, which always run once, as:
ball1=rand()%24;
do
{
ball2=rand()%24;
} while (ball2==ball1);
do
{
ball3=rand()%24;
} while ((ball3==ball2)||(ball3==ball1));
A much simpler way to do this is to use the facilities build into the C++ standard library:
#include <iostream>
#include <algorithm>
#include <random>
std::mt19937 gen(std::random_device{}()); // initialize random number generator
/*
* or
std::mt19937 gen(std::time(NULL));
* if std::random_device is not well-implemented
*/
int draw()
{
static int urn[24]={1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8};
std::shuffle(std::begin(urn), std::end(urn), gen); // shuffle array
return urn [0] + urn[1] + urn[2]; // pick first three balls from array
}
int main()
{
int discount = draw();
// Use discount. For example,
std::cout << discount;
return 0;
}
Documentation:
std::mt19937
std::random_device
std::shuffle

Execute code x percent of the time

I have an animal that lives in a while loop for many days.
At the end of the day, there is a 40% chance she gives birth,
class Animal
{
public:
double chance_of_birth;
...
public Animal(..., int chance)
{
this.chance_of_birth = chance;
...
}
}
// create this animal
Animal this_animal = new Animal(..., .50);
Given that every animal I create can have a specific chance of giving birth,
how can I write a condition that evaluates true only chance_of_birth percent of the time?
I know I want to use rand(), but I never used it like this before.
Along the lines of
if(this_animal->chance_of_birth ???)
{
//will give birth
}
Since c++11 you can use the library <random>. In the example below I'm using std::uniform_real_distribution<> to generate a random floating point value within the range 0 - 1
#include <iostream>
#include <random>
using namespace std;
double random(int min, int max)
{ // we make the generator and distribution 'static' to keep their state
// across calls to the function.
std::random_device rd;
static std::mt19937 gen(rd());
static std::uniform_real_distribution<> dis(min, max);
return dis(gen);
}
int main()
{
double f = random(0,1); // range 0 - 1
cout << f << '\n';
}
Now you can use that random floating point value in an if statement to run only when a condition is true.
if (f <= 0.40) { ... }

Random Numbers in C++

I'm creating a BlackJack Program. I want the cards to be randomly dealt. if i use the rand() function and initialize srand() to time(NULL) then all the cards turn out to be same. Any idea what the problem might be ?
//Cards.h
#include <iostream>
#include <time.h>
#include <cstdlib>
using namespace std;
class Cards
{
private:
int val_seed,suit_seed;
public:
int val[10];
string card[10];
int dealcard(int x)
{
srand();
val_seed=rand()%13 + 2;
suit_seed=rand()%4 + 1;
if(val_seed>=1 && val_seed<=10)
{
if(val_seed==10)
{
card[x]="10";
}
else
{
card[x]=val_seed+48;
}
}
else if(val_seed>10)
{
switch(val_seed)
{
case 11: card[x]="J"; val_seed=10; break;
case 12: card[x]="Q"; val_seed=10; break;
case 13: card[x]="K"; val_seed=10; break;
case 14: card[x]="A"; val_seed=11; break;
}
}
switch(suit_seed)
{
case 1: card[x]+='\3'; break;
case 2: card[x]+='\4'; break;
case 3: card[x]+='\5'; break;
case 4: card[x]+='\6'; break;
}
val[x]=val_seed;
}
};
//main.cpp
#include <cstdlib>
#include <iostream>
#include "Cards.h"
using namespace std;
int main(int argc, char *argv[])
{
Cards k;
for(int a=1; a<=9; a++)
{
k.dealcard(a);
}
for(int e=1; e<=9; e++)
{
cout<<k.card[e]<<"("<<k.val[e]<<")"<<" ";
}
cout<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Seed the number generator ONCE. If you run your function in a loop they will be executed faster than the time resolution interval (so all the seeds are the same and therefore the numbers).
While developing the app and debugging it it will help if you seed the generator with the same, known value. This means successive debugging sessions will use the same values from the generator.
Don't forget to switch back to a time() based seed in your release build (or use the pre-processor to detect if it's a Debug or Release build and do it for you).
See http://www.cplusplus.com/reference/clibrary/cstdlib/srand/
srand is best initialised with a unique value, eg, the time, as computers dont generate random numbers but in effect work from a predone list, this sets the start point to be less determinable.
You do not want to call srand every time you use rand, just call it once at the start of the program and you will be fine.
Calling it with the time as parameter will also make sure you will get a different random sequence each time you run the program.
Problems using srand() notwithstanding, your card generation algorithm is wrong. Even the possibility of it generating two of the same card in a row means it is wrong.
You should take a deck of cards (52 or some multiple thereof), shuffle it using a randomly generated seed, and deal cards from the shuffled deck.
You are seeding srand() with null; seed with current clock time and then retry it should solve your problem.
time_t now;
time(&now);
srand((unsigned int)now);