srand() is not working when used with non-constant parameter - c++

I've got a problem with srand(). It only works when I use a number as a parameter, for example srand(1234), but when I try to use it with 'n' or with time (as below), then randint() keeps returning the same value.
#include <iostream>
#include <experimental/random>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
srand(time(nullptr));
for (int i = 0; i < 4; ++i) {
int random = experimental::randint(0, 9);
cout << random;
}
}
Thanks for your time.

The C function srand is meant to be used in combination with the C function rand. These are separate functions from those in C++'s std::experimental header. The randint function from the latter is meant to be used with the reseed function from the same header:
#include <experimental/random>
#include <iostream>
int main() {
std::experimental::reseed();
for (int i = 4; i--; ) {
int random = std::experimental::randint(0, 9);
std::cout << random << '\n';
}
}
However, there is no need to use experimental features here. Since C++11, there is std::uniform_int_distribution:
#include <iostream>
#include <random>
int main() {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> distrib(0, 9); // Default type is 'int'
for (int i = 4; i--; ) {
int random = distrib(gen);
std::cout << random << '\n';
}
}
This method is more flexible than the one from the C standard library and should, generally, be preferred in C++.

Related

How can I set range to the random library

I really don't like the rand() function.I wanted to use the library but I don't really know how to set up a range for example from 1 to 3. I want to "random" these numbers(1,2,3) and not huge numbers like 243245.This code is how you can use the random library and print random numbers
#include <iostream>
#include <string>
#include <random>
using namespace std;
int main()
{
minstd_rand simple_rand;
simple_rand.seed(NULL);
for (int ii = 0; ii < 10; ++ii)
{
std::cout << simple_rand() << '\n';
}
}
Use std::uniform_int_distribution:
#include <ctime>
#include <iostream>
#include <random>
int main()
{
std::mt19937 rng(std::time(0)); // `std::minstd_rand` would also work.
std::uniform_int_distribution d(1,3);
for (int i = 0; i < 10; i++)
{
std::cout << d(rng) << '\n';
}
}
#include <iostream>
#include <random>
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<> dis(1, 3);
for (int n=0; n<10; ++n)
//Use dis to transform the random unsigned int generated by gen into an int in [1, 6]
std::cout << dis(gen) << ' ';
std::cout << '\n';
}
Thanks to #holyBlackCat Credit to: cppreference.com

How to generate different random number for the same variable

I want to use a while loop to generate a random number for a variable to spell out a scrambled word. My problem is that my code generates a number that is random but repeats that number rather than using a new number.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
string wordList[5] = {"cool", "friend", "helpful", "amazing",
"person"};
srand(time(0));
int rWord = rand() % 5 + 1;
string randWord = wordList[rWord];
int runs = 0;
int wordLen = randWord.length();
while(runs != wordLen){
int ranLN = rand() % wordLen;
char randLetter = randWord[ranLN];
cout << randLetter;
runs++;
}
return 0;
}
I expected my results to be a fully scrambled word, but I instead got repeated letters. For example, I got the word "friend" scrambled as "eennn".
As suggested in comments, the current range of rWord is 1,2,3,4,5 which must be fixed to 0,1,2,3,4.
Thus I removed +1 from it's initialization equation in the following answer.
In addition, ranLN can be duplicate thus you got repeated letters.
Then, a possible way is recursively shuffling all characters of randWord and output them after the while loop finished as follows.
The same algorithm is shown here as an example:
DEMO
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <utility>
int main()
{
std::string wordList[5] = {"cool", "friend", "helpful", "amazing", "person"};
srand(time(0));
std::size_t rWord = rand() % 5;
std::string randWord = wordList[rWord];
std::size_t runs = 0;
std::size_t wordLen = randWord.length();
while(runs != wordLen)
{
std::swap(randWord[runs], randWord[rand() % wordLen]);
++runs;
}
std::cout << randWord << std::endl;
return 0;
}
BTW, although rand() should be usually implemented by a something better LCG,
but, for instance as noted in (my local) C++ standard draft n4687, the algorithm used in rand() is completely compiler implementation defined:
29.6.9 Low-quality random number generation [c.math.rand]
int rand();
void srand(unsigned int seed);
... rand’s underlying algorithm is unspecified. Use of rand therefore continues to be non-portable, with unpredictable and oft-questionable quality and performance.
Fortunately, in C++11 and over, we can use <random> to generate a guaranteed quality randomness.
Thus I recommend you to use them with std::shuffle as follows.
If you need more high-quality randomness, you can use std::mt19937 instead of std::minstd_rand:
DEMO
#include <iostream>
#include <string>
#include <random>
#include <algorithm>
int main()
{
std::string wordList[5] = {"cool", "friend", "helpful", "amazing", "person"};
std::minstd_rand gen(std::random_device{}());
std::uniform_int_distribution<std::size_t> dis(0, 4);
std::size_t rWord = dis(gen);
std::string randWord = wordList[rWord];
std::shuffle(randWord.begin(), randWord.end(), gen);
std::cout << randWord << std::endl;
return 0;
}
In my humble opinion after generating all random words then using set data structure would make the random word unique.

How to include the max value of uniform_real_distribution

I am a beginner in C++ and I am trying to explore C++11 features. Here I am trying to get familiar with the new randomness generating engines.
I summarized the following code from a tutorial on this subject and I noticed two things:
1- The uniform_real_distribution doe not include the max value.
2- The commented line produce an error although it seems to work fine on the tutorial.
#include <iostream>
#include <random>
#include <chrono>
#include <string>
using namespace std;
int main(){
unsigned seed = 201;
//seed = chrono::steady_clock()::now().time_since_epoch().count();
default_random_engine e(seed);
uniform_real_distribution<double> u(0,9);
vector<double> v(10);
int num;
for(int i = 0; i < 400; ++i){
num = u(e);
++v[num];
}
for (int i = 0; i < 10; ++i)
cout << i << ": " << string(v[i],'*') << "\n";
}
I tried to find the reasons of these two things with no luck.
So, my questions:
1- How to include the max value?
2- Why I am getting the error when uncomment the chrono line ?
cannot convert 'std::chrono::_V2::steady_clock' to 'unsigned int' in initialization
Note: I am using MinGW64 g++ with c++14.
As already said by Chris Drew, you can use nextafter as the second parameter of uniform_real_distribution.
Note that you first instantiate a new object chrono::steady_clock (with chrono::steady_clock() ) and then try to call the static member now() from this object.
As now() is a static member function of chrono::steady_clock, you can (and should) directly call chrono::steady_clock::now().
Final code:
#include <iostream>
#include <random>
#include <chrono>
#include <string>
using namespace std;
int main(){
unsigned seed = 201;
seed = chrono::steady_clock::now().time_since_epoch().count();
default_random_engine e(seed);
uniform_real_distribution<double> u(0,std::nextafter(9, std::numeric_limits<double>::max()));
vector<double> v(10);
int num;
for(int i = 0; i < 400; ++i){
num = u(e);
++v[num];
}
for (int i = 0; i < 10; ++i)
cout << i << ": " << string(v[i],'*') << "\n";
}

Random number generator generating the same number even after seeding

Here's my code:
#include <iostream>
#include <string>
#include <random>
#include <ctime>
using namespace std;
int RandomIntGen(int lowerLimit, int upperLimit);
int main()
{
for (int i = 0; i < 10; i++) {
cout << "I am rolling a " << RandomIntGen(1, 6) << endl;
}
system("PAUSE");
}
// A random integer generator that takes in a upper and lower integer limit and returns a random integer
int RandomIntGen(int lowerLimit, int upperLimit) {
default_random_engine randomGenerator(time(0)); //seeding with time
uniform_int_distribution<int> randomInteger(lowerLimit, upperLimit);
return randomInteger(randomGenerator);
}
Don't know why it's generating the same value even with seeding. How do I fix this?
Moved "default_random_engine randomGenerator(time(0));" to global space to make sure it is seeded only once.
#include <iostream>
#include <string>
#include <random>
#include <ctime>
using namespace std;
//Random Generator with Seed
default_random_engine randomGenerator(time(0));
// Function Declarations
int RandomIntGen(int lowerLimit, int upperLimit);
int main()
{
for (int i = 0; i < 10; i++) {
cout << "I am rolling a " << RandomIntGen(1, 6) << endl;
}
system("PAUSE");
}
// A random integer generator that takes in a upper and lower integer limit and returns a random integer
int RandomIntGen(int lowerLimit, int upperLimit) {
uniform_int_distribution<int> randomInteger(lowerLimit, upperLimit);
return randomInteger(randomGenerator);
}

random function in C++

Is there a function that generates k random numbers within a specified range.
For example I want 5 random numbers between 0 to 100, with or without replacement.
You could use std::generate_n with either rand() or a generator from the new C++11 random number generators.
There is the Boost library, which you can use to generate random numbers, for example.
The following code generates 5 random numbers from [0, 100] with replacement:
#include <vector>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
const int numWantedNumbers = 5;
int main()
{
boost::random::mt19937 generator;
boost::random::uniform_int_distribution<> distribution(0, 100);
std::vector<int> result;
for (int i = 0; i < numWantedNumbers; ++i)
result.push_back(distribution(generator));
}
If you want to generate the numbers without replacement, simply check if they are
still available:
#include <algorithm>
#include <vector>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
const int numWantedNumbers = 5;
int main()
{
boost::random::mt19937 generator;
boost::random::uniform_int_distribution<> distribution(0, 100);
std::vector<int> result;
while (result.size() < numWantedNumbers)
{
int number = distribution(generator);
if (std::find(result.begin(), result.end(), number) == result.end())
result.push_back(number);
}
}
Note: The rejection sampling in the example without replacement has the obvious drawback that longer vectors are quite difficult to create. Just try to draw 99 out
of 100 numbers, to see what I mean (or even better draw 9999 out of 10000). If this
is a problem, I would suggest to create a random permutation of all possible numbers
and then cut the vector at the requested size:
#include <algorithm>
#include <vector>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
const int numWantedNumbers = 5;
int main()
{
boost::random::mt19937 generator;
boost::random::uniform_int_distribution<> distribution(0, 100);
// Generate a vector with all possible numbers and shuffle it.
std::vector<int> result;
for (int i = 0; i <= 100; ++i)
result.push_back(i);
for (int i = 0; i <= 100; ++i)
{
int x = distribution(generator);
std::swap(result[i], result[x]);
}
// Truncate to the requested size.
result.resize(numWantedNumbers);
}
Edit based on suggestion by juanchopanza:
In C++11 manner, the last variant would look like this
#include <algorithm>
#include <random>
#include <vector>
const int numWantedNumbers = 5;
int main()
{
std::random_device device;
std::mt19937 generator(device());
std::uniform_int_distribution<> distribution(0, 100);
// Generate a vector with all possible numbers and shuffle it.
std::vector<int> result;
for (int i = 0; i <= 100; ++i)
result.push_back(i);
std::random_shuffle(result.begin(), result.end());
// Truncate to the requested size.
result.resize(numWantedNumbers);
}
g++-4.6 compiles it happily, if you add the -std=c++0x switch.
Edit: Make use of std::random_shuffle() (tanks to James Kanze).
Yes there is a rand() function in C++ which can be used including cstdlib header file in your program.
You can implement your program using the following code.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
int max {100};
int min {0};
int number;
int count = 5; //assuming that only 10 numbers we need to print
srand(time(0));
for(int i=1;i<=count;i++)
{
number = rand() % (max - min +1) + min;``
cout<<number<<endl;
}
}