My result is not truly random; How can I fix this? - c++

float genData(int low, int high);
int main(){
srand(time(0));
float num = genData(40, 100);
cout << fixed << left << setprecision(2) << num << endl;
return 0;
}
float genData(int low, int high) {
low *= 100;
high *= 100 + 1;
int rnd = rand() % (high - low) + low;
float newRand;
newRand = (float) rnd / 100;
return newRand;
}
I'm expecting a random number between 40 and 100 inclusively with two decimal places.
eg: 69.69, 42.00
What I get is the same number with different decimal values, slowly increasing every time I run the program.

Use the <random> header for that:
#include <iostream>
#include <random>
float getData(int const low, int const high) {
thread_local auto engine = std::mt19937{ std::random_device{}() };
auto dist = std::uniform_int_distribution<int>{ low * 100, high * 100 };
return dist(engine) / 100.0f;
}
int main() {
for (auto i = 0; i != 5; ++i) {
std::cout << getData(40, 100) << '\n';
}
}

Wrong range
int rnd = rand() % (high - low) + low; does not generate the right range.
float genData(int low, int high) {
low *= 100;
// high *= 100 + 1;
high = high*100 + 1;
expecting a random number between 40 and 100 inclusively with two decimal places. eg: 69.69, 42.00
That is [40.00 ... 100.00] or 10000-4000+1 different values
int rnd = rand() % (100*(high - low) + 1) + low*100;
float frnd = rnd/100.0f;
rand() weak here when RAND_MAX is small
With RAND_MAX == 32767, int rnd = rand() % (high - low) + low; is like [0... 32767] % 6001 + 40000. [0... 32767] % 6001 does not provide a very uniform distribution. Some values coming up 6 times and others 7-ish.

If you are using C++ 11 you can use better random number generators that will give you diversity in the generated numbers in addition to being a lot faster.
Quick Example:
#include <random> // The header for the generators.
#include <ctime> // To seed the generator.
// Generating random numbers with C++11's random requires an engine and a distribution.
mt19937_64 rng(seed);
// For instance, we will create a uniform distribution for integers in the (low, high) range:
uniform_int_distribution<int> unii(low, high);
// Show the random number
cout << unii(rng) << ' ';
You can follow this article for more explanation from here.

Related

Why does rand from stdlib not follow law of large numbers?

In the following code, in which I expect a die that roles bilions of times that the average outcome to be exactly 3.5, the percentage that lies above 3.5 sometimes is like 5 percent and other times (with different seed of course) is like 95. But even when you go as high as 6040M thows, you never end up near 50% above, 50% under 3.5? Obviously there's a little bias in rand()...
I know about the fact that 'real random' doesn't exist but is it really this obvious?
Typical outputs are:
Average: 3.50003 counter: 3427000000 Percentage above: 83.2554 Perc abs above counter: 50.0011
Average: 3.49999 counter: 1093000000 Percentage above: 92.6983 Perc abs above counter: 50.0003
#include <stdio.h> /* printf, scanf, puts, NULL */
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <unistd.h>
#include <iostream>
using namespace std;
int main ()
{
long long int this_nr;
long long int counter = 0;
long long int above_counter = 0;
long long int below_counter = 0;
long long int above_counter_this = 0;
long long int below_counter_this = 0;
long long int interval_counter = 0;
double avg = 0.0;
srand (time(NULL));
srand (time(NULL));
srand (time(NULL));
cout.precision(6);
while(1) {
this_nr = rand() % 6 + 1; // 0,1,2,3,4,5 or 6
avg = ((double) this_nr + ((double)counter * (double) avg))
/ ((double) counter+1.0);
if (this_nr <= 3) below_counter_this++;
if (this_nr >= 4) above_counter_this++;
if (avg < 3.5) below_counter++;
if (avg > 3.5) above_counter++;
if (interval_counter >= 1000000) {
cout << "Average: " << avg << " counter: " << counter << " Percentage above: "
<< (double) above_counter / (double) counter * 100.0
<< " Perc abs above counter: " << 100.0 * above_counter_this / counter
<< " \r";
interval_counter = 0;
}
//usleep(1);
counter++;
interval_counter++;
}
}
rand() is well known to be a terrible generator, and it's particularly bad in the low bits. Performing % 6 is picking off only the low bits. There's also a chance that you're experiencing some modulo bias, but I'd expect that effect to be relatively minor.

Discrete Event simulation generates different results in windows and linux

I am doing a m/m/2/2 discrete event simulation. The result is same as the theoretical value, which means the program is correct (in Ubuntu, g++). However, when I tested the code again in windows (visual studio), the result is only correct when number of trials is less than 10000. I debugged for a very long time and finally find I have to use (double) rand() / ( RAND_MAX + 1 ) rather than just (double) rand() / RAND_MAX.
Why is that? Do these two compiler generate random in different ways?
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <cmath>
#include "iomanip"
#include <queue>
using namespace std;
#define TRIAL_NUM 10000000
//structure that represent a customer
struct cust
{
int cust_id;
double arrival_time;
double depart_time;
};
//uniform random generator
double uniRand()
{
return (double) rand() / RAND_MAX;
}
//exponential random generator
double expRand(double lam)
{
double u,x;
u=uniRand();
x=(-1/lam)*log(1-u);
return(x);
}
int main()
{
//seed the random generator
srand (time(NULL));
//queue that hold all customers
std::queue<cust*> customers;
double lam = 0, mu = 0;
bool showStatus = false;
cout<<"M/M/1/1 Discrete Event Simulation with "<<TRIAL_NUM<<" customers\n"<<" Please spacify the value of lambda:";
cin>>lam;
while(lam<= 0)
{
cout<<"lambda value must be a positive number, try again:";
cin>>lam;
}
cout<<"Please specify the value of mu:";
cin>>mu;
while(mu<= 0)
{
cout<<"lambda value must be a positive number, try again:";
cin>>mu;
}
cout<<"Show status for each customer? (y/n)";
char show;
cin>>show;
while( tolower(show) != 'y' && tolower(show) != 'n')
{
cout<<"Invalid input, try again:";
cin>>show;
}
if ( tolower(show) =='y' )
{
showStatus = true;
}
//Generating all arrival time, service time for all customers
double temp_time = 1;
cust* temp;
for (int i = 1; i <= TRIAL_NUM; ++i)
{
temp= new cust;
temp -> arrival_time = temp_time + expRand(lam);
temp_time = temp->arrival_time;
temp->depart_time = temp->arrival_time + expRand(mu);
temp->cust_id = i;
customers.push(temp);
}
//Blocking customer count
double block = 0;
bool blockFlag = false;
temp = customers.front();
double server1 = 0, server2 = 0;
//perform simulation
while( !customers.empty())
{
if ( server1 < temp->arrival_time)
{
server1 = temp->depart_time;
}
else if ( server2 < temp->arrival_time)
{
server2 = temp->depart_time;
}
else
{
block++;
blockFlag = true;
}
if (showStatus)
{
cout<<"Customer "<<temp->cust_id<<"\tarrived at:"<<temp->arrival_time<<"\tservice time:"<<temp->depart_time<<"\tstatus:";
if (blockFlag)
{
cout<<"Blocked"<<endl;
}
else{
cout<<"Served"<<endl;
}
}
customers.pop();
if (!customers.empty())
{
temp = customers.front();
}
blockFlag = false;
}
cout<<"Blocking probability is: "<<block/TRIAL_NUM<<endl;
return 0;
}
(double) rand() / (RAND_MAX + 1) is a dangerous expression.
If, as it often happens, RAND_MAX is equal to INT_MAX then RAND_MAX + 1 is an overflow and undefined behaviour (it usually results in INT_MIN but this is not guaranteed by any specification).
In Visual C++ RAND_MAX is 32767 and you haven't this problem (but 32767 is a small value it "starts cycling" quite quickly).
Anyway I think that the real problem is here:
u = uniRand();
x = (-1 / lam) * log(1 - u);
When uniRand() is defined as (double) rand() / RAND_MAX it produces values in the range:
0.0 <= uniRand() <= 1.0
and when the value is equal to 1.0 you have a pole error in your log(1-u). This will happen more frequently with Visual C++ because of the small value of RAND_MAX.

Generate random int with specified upper-bound (0 - n) without using / or %

roommate went to an interview and got this one:
Rules:
permitted to use rand();
RAND_MAX = 32 767;
no use of division or modulo;
TODO:
Write a function that takes one int parameter and returns
int in range 0 - parameter.
Head hurts, can't sleep. Any help appreciated.
Thanks
Few possibilities:
the range transposition approach: int r = rand() * 0.00003051855095 * n;
the "shuffle sort" approach: int r; do { r = random(); } while (r >= n);
the BSD approach: uint32_t r = arc4random_uniform(n);
Etc., etc., etc.
In my public domain randlib, I do it with
no floating point, no division, no multiplication, just bitmasking and rejection sampling, like this:
int ojr_rand(ojr_generator *g, int limit) {
int v, m = limit - 1;
m |= m >> 1;
m |= m >> 2;
m |= m >> 4;
m |= m >> 8; // m is smallest ((power of 2) - 1) > limit
do {
v = m & NEXT16(g); // 16-bit random number
} while (v >= limit);
return v;
}
In the worst case (limit is power of two plus one), this can reject close to 50% of the generated numbers, but it's still faster than division or floating math with most fast RNGs, and in the general case it's much faster. Also, unlike the floating point math or mod, it is exact, meaning if you ask for a limit of 3, you get values 0, 1, and 2 with exactly equal probability, not just approximately equal.
If c++11 is allowed there is a random header provided that makes this trivial:
#include <random>
#include <iostream>
int Roll(int Max)
{
if(Max>32767)
Max=32767;
std::random_device generator;
std::uniform_int_distribution<int> distribution(0,Max);
return distribution(generator);
}
int main()
{
std::cout << Roll(10) << std::endl
<< Roll(10) << std::endl
<< Roll(999999) << std::endl;
}
More details at: http://en.cppreference.com/w/cpp/numeric/random
This presumes that RAND_MAX is provided by your problem and not by the C standard of course you could use the provided constant, for details see: http://en.cppreference.com/w/cpp/numeric/random/RAND_MAX
do { r = random();} while (r >= max_rand);
At first I thought multiplying by a fraction would work but that could be considered cheating from a mathematical standpoint.
int getRand(int max)
{
int val = rand();
while (val > max)
{
val -= max + 1;
}
return val;
}
This will obviously be off slightly by counting values <= RAND_MAX % max once more than everything else but rand() % max has the same problem so I assume this error to be acceptable (for values of max << MAX_RAND the error is insignificant).

Random number between two range

rand() or qrand() functions generate a random int.
int a= rand();
I want to get an random number between 0 and 1.
How I can do this Work?
You can generate a random int into a float, and then divide it by RAND_MAX, like this:
float a = rand(); // you can use qrand here
a /= RAND_MAX;
The result will be in the range from zero to one, inclusive.
Using C++11 you can do the following:
Include the random header:
#include<random>
Define the PRNG and the distribution:
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(0.0,1.0);
Get the random number
double number = distribution(generator);
In this page and in this page you can find some references about uniform_real_distribution.
Check this post, it shows how to use qrand for your purpose which is afaik a threadsafe wrapper around rand().
#include <QGlobal.h>
#include <QTime>
int QMyClass::randInt(int low, int high)
{
// Random number between low and high
return qrand() % ((high + 1) - low) + low;
}
#include <iostream>
#include <ctime>
using namespace std;
//
// Generate a random number between 0 and 1
// return a uniform number in [0,1].
inline double unifRand()
{
return rand() / double(RAND_MAX);
}
// Reset the random number generator with the system clock.
inline void seed()
{
srand(time(0));
}
int main()
{
seed();
for (int i = 0; i < 20; ++i)
{
cout << unifRand() << endl;
}
return 0;
}
Take a module from the random number which will define the precision. Then do a typecast to float and divide by the module.
float randNum(){
int random = rand() % 1000;
float result = ((float) random) / 1000;
return result;
}

Random number between 1 to 10 using C++

This code is supposed to generate random number between 1 to 10, but it returns 1 every time.
int random_integer;
int lowest=1, highest=10;
int range=(highest-lowest)+1;
random_integer = lowest + int(range*rand()/(RAND_MAX + 1.0));
cout << random_integer << endl;
What's wrong in the code?
If you want a random integer between lowest and highest, you'd better write
random_integer = lowest + rand() % range
You're subject to overflow here - range*rand().
Just use what regular folks use: rand() % 10 + 1.
range * rand() / (RAND_MAX + 1.0)
does not do what you think. Introduce some parens:
range * (rand() / (RAND_MAX + 1.0))
(Note that this method gives skewed distributions, though.)
I agree with all the solution provided above .
now to get a different sequence every time you run your program you can use srand() function it will provide a seed to rand() function as follows:-
srand(time(NULL))
random_integer = lowest + rand() % range
This two are always part of my programs
float randf(float lo, float hi) {
float random = ((float) rand()) / (float) RAND_MAX;
float diff = hi - lo;
float r = random * diff;
return lo + r;
}
int randi(int lo, int hi)
{
int n = hi - lo + 1;
int i = rand() % n;
if (i < 0) i = -i;
return lo + i;
}
You seem to assume that rand() returns a value between 0 and 1.
This is not correct, it return value between 0 and RAND_MAX.