passing a seed through different boost random number generator - c++

I am passing a streamstring from one random generator to another to keep track of the current state of an engine (boost random library). It allows me stop at any point and save the current state to reproduce a series later on in the code or continue it.
It works fine until I use different random generators while passing the same stringstream (as reproduce bellow). I cannot use different streams for the two, as in the real example a class will call to different distributions in a random order...
#ifndef RANDOM_HPP
#define RANDOM_HPP
namespace RandomG{
using namespace std;
using namespace boost::random;
int getSeed()
{
ifstream rand("/dev/urandom");
char tmp[sizeof(int)];
rand.read(tmp,sizeof(int));
rand.close();
int* number = reinterpret_cast<int*>(tmp);
return (*number);
}
void Get_Rstream(stringstream &s)
{
mt19937 randgen(getSeed());
s.clear();
s << randgen;
}
template<class distribution>
class Random
{
public:
Random(distribution nd)
{
mt19937 randgen(getSeed());
rng=new variate_generator<mt19937,distribution >(randgen, nd);
}
virtual ~Random()
{
delete rng;
}
void reset(void)
{
(*rng).distribution().reset();
}
double operator()(stringstream &s)
{
double x;
s >> (*rng).engine();
x=(*rng)();
return x;
}
variate_generator<mt19937,distribution > *rng;
};
}
#endif
So now if I instantiate two instances of these classes (below its two uniform but it could be a uniform and a Gaussian or anything else and could be called in a random order).
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include "Random.hpp"
using namespace boost::random;
using namespace std;
int main()
{
int M=20;
stringstream ss;
RandomG::Get_Rstream(ss);
string ss2=ss.str();
stringstream ss3;
ss3.clear();
ss3.str(ss.str());
boost::random::uniform_01<> N;
RandomG::Random<boost::random::uniform_01<> > *unif_rand1= new RandomG::Random<boost::random::uniform_01<> >(N);
boost::random::uniform_01<> U;
RandomG::Random<boost::random::uniform_01<> > *unif_rand2=new RandomG::Random<boost::random::uniform_01<> >(U);
(*unif_rand1).reset();
(*unif_rand2).reset();
for(int i=0;i<M;i++)
{
cout << (*unif_rand1)(ss) << " ";
}
for(int i=0;i<M;i++)
{
cout << (*unif_rand2)(ss) << " ";
}
cout <<"\\\\\\\\\\\\\\\\\\\\"<<"\n";
(*unif_rand1).reset();
(*unif_rand2).reset();
for(int i=0;i<M;i++)
{
cout << (*unif_rand1)(ss3) << " ";
}
for(int i=0;i<M;i++)
{
cout << (*unif_rand2)(ss3) << " ";
}
return 0;
}
This should give me two series of the same random numbers, but instead gives me the same random numbers for unif_rand1 but not for unif_rand2.
From what I understood feeding the same state to two different random number generator should give the same result or is there some way to reset them between draws ?
results:
0.525384 0.038626 0.563798 0.705042 0.725001 0.311586 0.843047 0.606338 0.163695 0.437574 \\\\\\\\\\
0.525384 0.038626 0.563798 0.705042 0.725001 0.0566288 0.93966 0.417343 0.686245 0.84118
Thanks for any responses or advises
(the code should be reproducible under linux).

Related

Linear vector search too slow for online judge

Problem Statement: We have to input a vector and then there is a certain number of queries. For one particular query, we have to search for that number in the vector. If found we print."Yes " and if not found we print the next greater number to the query and print "No ".
The vector is sorted.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int size,q,nq=0;
cin>>size;
vector<int> vec1;
int element;
for (int i = 0; i < size; i++)
{
cin>>element;
vec1.push_back(element);
}
cin>>q;
for(int j=0;j<q;j++)
{
cin>>nq;
for(int k=0;k<vec1.size();k++)
{
if(vec1[k]==nq)
{
cout<<"Yes "<<k+1<<endl;
break;
}
else if(vec1[k]>nq)
{
cout<<"No "<<k+1<<endl;
break;
}
}
}
return 0;
}
The code runs perfectly but for some test cases, there is an error due to time.
I need to improve this code. I am struggling with this as I have just learned about std::vector.
as this problem related to sorted vector it requires use Binary Search.
Binary search allows to answer queries with O(Log(N)) vs O(N) complexity (https://en.wikipedia.org/wiki/Computational_complexity). So this is why your implementation is too slow for this problem.
Here is manual implementation Using Binary Search with Vectors.
And also it is more clear to use std::lower_bound function. It does exact the thing needed:
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int size,q,nq=0;
cin>>size;
vector<int> vec1;
int element;
for (int i = 0; i < size; i++)
{
cin>>element;
vec1.push_back(element);
}
cin>>q;
vector<int>::iterator qit;
for(int j=0;j<q;j++)
{
cin>>nq;
qit = std::lower_bound(vec1.begin(), vec1.end(), nq);
if(qit != vec1.end())
{
if(*qit == nq)
cout << "Yes " << (qit - vec1.begin());
else cout << "No " << *qit << " " << (qit - vec1.begin());
}
else cout << "No " << (qit - vec1.begin());
}
return 0;
}

vector with reinterpret_cast

The following code inserts only one value to the vector col.
The code is extracted from DBMS code base (for importing files), specifically, it is from 1
The code uses void* to be able to read any field type (int, float, and so on).
#include <iostream>
#include <vector>
using namespace std;
void add(std::vector<void*> &col){
reinterpret_cast<std::vector<int>&>(col).push_back( 1);
reinterpret_cast<std::vector<int>&>(col).push_back( 2);
reinterpret_cast<std::vector<int>&>(col).push_back( 13);
}
int main() {
std::vector<void*> col;
add(col);
cout << col.size() << endl;
for(int i=0;i<col.size();i++)
cout <<reinterpret_cast<std::vector<int>&> (col)[i] <<endl;
return 0;
}
I am not sure how this code work?
Your code is exhibiting undefined behavior.
std::vector<void*> and std::vector<int> are two completely separate and unrelated types, you can't safely cast between them the way you are, especially since there is no guarantee that void* and int are the same byte size.
Cast the values you are pushing, don't cast the vector itself, eg:
#include <iostream>
#include <vector>
#include <cstdint>
using namespace std;
void add(std::vector<void*> &col) {
col.push_back(reinterpret_cast<void*>(static_cast<intptr_t>(1)));
col.push_back(reinterpret_cast<void*>(static_cast<intptr_t>(2)));
col.push_back(reinterpret_cast<void*>(static_cast<intptr_t>(13)));
}
int main() {
std::vector<void*> col;
add(col);
cout << col.size() << endl;
for(int i=0;i<col.size();i++)
cout << reinterpret_cast<intptr_t>(col[i]) << endl;
return 0;
}
Of course, you really should be using the proper container type to begin with:
#include <iostream>
#include <vector>
using namespace std;
void add(std::vector<int> &col) {
col.push_back(1);
col.push_back(2);
col.push_back(13);
}
int main() {
std::vector<int> col;
add(col);
cout << col.size() << endl;
for(int i=0;i<col.size();i++)
cout << col[i] << endl;
return 0;
}

Can't put class with main function?

Something I am working on is making a code that focuses on making a class that reverses an order of numbers. This will then get put into the main code that will eliminate any trailing zeroes. I can't seem to wrap my head around how classes work and where I am going wrong. Here is my code:
Numbers.h
#pragma once
#include <iostream>
class Numbers
{
public:
int digit
private:
void Numbers::reverse();
};
Numbers.cpp
#include "Numbers.h
#include <iostream>
using namespace std;
void Numbers::reverse(){
int n, reversedNumber = 0, remainder;
cout << "Enter the number you would like to manipulate! " << endl;
cin >> n;
while (n !=0)
{
remainder = n % 10;
reversedNumber = reversed Number * 10 + remainder;
n /= 10;
}
//return *this;
}
Main.cpp
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <string>
#include "Numbers.h"
using namespace std;
int main()
{
Numbers.reverse;
system("pause");
return 0;
}
I can't seem to make the reverse function in my Numbers.cpp work in the main function. I am new to C++ and am not sure where I am going wrong. Any help would be appreciated!
OK, there are a lot of mistakes or learning errors in your code. Your header file should look something like:
#pragma once
class Numbers
{
public:
Numbers();
~Numbers();
int Reverse(int input); // Function is 'public'.
};
Your CPP file will then be (parts taken from S.O. post here):
#include "Numbers.h"
Numbers::Numbers()
{
}
Numbers::~Numbers()
{
}
// No need to store the value in 'digit' since this
// is just an algorithm which can return the result.
int Numbers::Reverse(int input)
{
int ret = 0;
while(input > 0)
{
ret = ret * 10 + (input % 10);
input = input / 10;
}
return ret; // Return the reversed number and let the user decide what to do.
}
Then you can use your class as follows:
#include "Numbers.h"
#include <iostream>
using namespace std;
int main()
{
int num;
cout << "Enter a number to reverse: ";
cin >> num;
Numbers numClass;
cout << "Reversed number is: " << numClass.Reverse(num) << endl;
return 0;
}

Error/Exception catching within a class

I have written a class that returns a random string after you provide a seed, a sequence length, and a character set as shown below.
I would like to know how to catch any bad input, such as setting the seed to 0 or to a negative number.
The examples that I have seen have just used cout to send an error message and then exit(1); I am thinking about putting a bool flag as a private variable and setting it to false when invalid input is detected. Then after you attempt to generate a random string with this class you would just check that flag through an accessor function.
Is there a better and/or standard way of handling this that will not just exit the program like exit(1)? Any general input about the class is welcomed also. Thanks for the assistance.
RandomString.h
// This is the header file randomstring.h. This is the interface for the class RandomString.
// Values of this type are a random string of the specified length from the specified string character set.
// The values that are needed for input are a positive integer seed, an integer desired length, and a string character set.
// Uses the mt19937 random number engine with a uniform_int_distribution.
#ifndef RANDOMSTRING_H
#define RANDOMSTRING_H
#include <string>
#include <random>
using namespace std;
namespace RandomString
{
class RandomString
{
public:
RandomString(double newSeed, unsigned int newLength, string newCharacterSet); // Initializes the RandomString object with the provided arguments.
RandomString(); // Initializes the seed to 1, the length to 0, and the character set to '0'.
double getSeed();
unsigned int getLength();
string getCharacterSet();
string getSequence();
void setSeed(double newSeed); // Sets the new seed but does not produce a new random sequence.
void setLength(unsigned int newLength); // This is the length of randomSequence.
void setCharacterSet(string newCharacterSet);
void generateNext(); // Generates the next random sequence.
private:
double seed;
unsigned int length;
string characterSet;
string randomSequence;
mt19937 engine;
};
} // RandomString namespace
#endif
RandomString.cpp
// This is the implementation file randomstring.cpp. This is the implementation for the class RandomString.
// The interface for the class RandomString is in the header file randomstring.h.
#include "stdafx.h"
#include <string>
#include <random>
#include "randomstring.h"
using std::string;
using std::uniform_int_distribution;
namespace RandomString
{
RandomString::RandomString(double newSeed, unsigned int newLength, string newCharacterSet)
{
setSeed(newSeed);
setLength(newLength);
setCharacterSet(newCharacterSet);
}
RandomString::RandomString()
{
seed = 1;
length = 0;
characterSet = '0';
}
double RandomString::getSeed()
{
return seed;
}
unsigned int RandomString::getLength()
{
return length;
}
string RandomString::getCharacterSet()
{
return characterSet;
}
string RandomString::getSequence()
{
return randomSequence;
}
void RandomString::setSeed(double newSeed)
{
seed = newSeed;
engine.seed(seed);
}
void RandomString::setLength(unsigned int newLength)
{
length = newLength;
}
void RandomString::setCharacterSet(string newCharacterSet)
{
characterSet = newCharacterSet;
}
void RandomString::generateNext()
{
randomSequence.resize(length);
uniform_int_distribution<> distribution(0,characterSet.length() - 1);
for (int i = 0; i < length; i++)
{
randomSequence[i] = characterSet[distribution(engine)];
}
}
} // RandomString namespace
Finally, here is the test program that I am using.
// test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "randomstring.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
do
{
double seed = 0;
unsigned int length = 0;
cout << "Enter seed: ";
cin >> seed;
cout << "Enter length of string: ";
cin >> length;
cout << endl;
RandomString::RandomString randomTest(seed,length,"ABCDEFGHJKLMNPQRSTUVWXYZ1234567890");
cout << "class RandomString" << endl;
cout << "seed: " << randomTest.getSeed() << endl;
cout << "length: " << randomTest.getLength() << endl;
randomTest.generateNext();
cout << "random sequence: " << randomTest.getSequence() << endl;
randomTest.generateNext();
cout << "next random sequence: " << randomTest.getSequence() << endl << endl;
}while(true);
}
Throw an exception
void RandomString::setSeed(double newSeed)
{
if (newSeed <= 0) {
throw std::runtime_error("seed should be positive");
}
seed = newSeed;
engine.seed(seed);
}
User would have to use try catch to handle error, else std::terminate is called.
How about letting the user have another chance at giving a good input?
What is the next thing the user will do after they find out they have put in a bad input? There is a high chance they will try again with a good input so just ask for another one.
while(true)
{
cout << "Enter seed: ";
cin >> seed;
if(seed > 0)
{
cout << "ERROR: Seed must be greater than 0." << endl;
break;
}
}
To answer your question about the bool error flag, I wouldn't do it that way. I have no need for bad data that was generated from a bad seed. No data is better than bad data. I generally try to "fail early, fail often", meaning I should stop and report the error as soon as I realize it exists.
If you were set on storing it the error flag, I'd have generateNext() or setSeed return false rather than nothing if there was a problem. Exceptions also work, but are slower and some projects don't like them in C++.
If you plan to have others use RandomString, I'd change the method signature from a double to uint (unsigned int). This would catch negative numbers being used at compile time rather than run time...again helping to fail even earlier. Sounds like this might not work in your classroom scenario, but is a good principle in the real world.

C++ Error: No Member in Class?

I'm working on C++, and this is just a very basic program, but I'm still getting an error.
The error message is:
'class secondary' has no member named 'getting'.
Why is this? It works for my void setting, but not for getting? What am I doing wrong here?
main.cpp
#include <iostream>
#include <string>
#include "secondary.h"
using namespace std;
int main(){
secondary s;
int scale;
cout << "On a scale of 1-10, how awesome are you?" << endl;
cin >> scale;
cout << endl;
s.setting(scale);
cout << s.getting();
return 0;
}
secondary.h
#ifndef SECONDARY_H
#define SECONDARY_H
#include <string>
class secondary
{
public:
void setting(int x);
string getting();
};
#endif // SECONDARY_H
secondary.cpp
#include "secondary.h"
#include <iostream>
#include <string>
using namespace std;
void secondary::setting(int x){
factor = x;
}
string secondary::getting(){
string result;
if(factor < 3){
result = "You have a very low self esteem.";
}elseif(factor > 3){
if(factor > 7){
result = "You have a very high self esteem."
}else{
result = "You have a medium self esteem."
}
}
return result;
}
private factor;
Actually, looking at this again, and deeper, this code has many issues (semicolons missing at key points and the private int definition should have been in the header file, not the cpp file 9t(private is its own section, see below):The problem, from what I can see, s has not yet been instantiated yet, do so and the operation should work correctly.
Please also note that when factor was defined in the cpp file, it was defined at bottom, it should actually be defined before any use of the variable to be defined (in the header file is better meet with common/conventional coding standards).
Please check this tested code:
main.cpp
#include <iostream>
#include <string>
#include "secondary.h"
using namespace std;
int main(){
secondary s;
int scale;
cout << "On a scale of 1-10, how awesome are you?" << endl;
cin >> scale;
cout << endl;
s.setting(scale);
cout << s.getting();
return 0;
}
secondary.h
#ifndef SECONDARY_H
#define SECONDARY_H
#include <string>
class secondary
{
public:
void setting(int x);
std::string getting();
private: // Note: this is how you do private
int factor; // This is the definition with type int, missing in original
};
#endif // SECONDARY_H
secondary.cpp
#include "secondary.h"
#include <iostream>
#include <string>
using namespace std;
void secondary::setting(int x){
factor = x;
}
string secondary::getting(){
string result;
if (factor < 3){
result = "You have a very low self esteem.";
}else if(factor > 3){
if (factor > 7){
result = "You have a very high self esteem.";
}
else{
result = "You have a medium self esteem.";
}
}
return result;
}