I need to generate a large number of random multiprecision ints (boost mpx_int) of various bits. My current approach is based on these two examples: boost multiprecision random, constexpr array. To generate a random number this way I need the number of bits as a constexpr. I can generate an array of constexpr ints, but then I get stuck because I cannot access them from within a for loop.
Code example:
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/random.hpp>
#include <iostream>
using namespace std;
using namespace boost::multiprecision;
using namespace boost::random;
template <int bit_limit>
struct N_bit_nums
{
constexpr N_bit_nums() : bits{}
{
for (int i = 0; i < bit_limit; ++i)
{
bits[i] = i + 1;
}
}
int bits[bit_limit];
};
int main()
{
constexpr int bit_limit = 3; // this will actually be on the order of 10^6
constexpr N_bit_nums<bit_limit> n_bit_nums{};
for (int i = 0; i < bit_limit; ++i)
{
independent_bits_engine<mt19937, n_bit_nums.bits[i], cpp_int> generator; // error: the value of āiā is not usable in a constant expression
cpp_int rand_num = generator();
cout << rand_num << "\n"; // just to see what is going on while testing
}
return 0;
}
I was able to accomplish this by fixing the independent_bits_engine to the largest amount of bits needed and then masking to the number of bits required.
Example:
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/random.hpp>
#include <iostream>
using namespace std;
using namespace boost::multiprecision;
using namespace boost::random;
int main()
{
constexpr int bit_limit = 100;
independent_bits_engine<mt19937, bit_limit, cpp_int> generator;
// prints random numbers of bit sizes from 1 to bit_limit
for (int n = 1; n <= bit_limit; n++)
{
cpp_int rand_num = generator(); // next random value
cpp_int n_bit_mask = pow(cpp_int{2}, n) - 1; // n bits mask
cpp_int n_bit_num = rand_num & n_bit_mask; // take n lsb
cout << n_bit_num << "\n"; // print the n bit random number
}
return 0;
}
Related
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++.
I need my program to make a random sequence from 1-3 each time, but I don't understand how I'd use rand() to make the sequence of numbers 1 to 3 in a different order each program. It can't be the same number again, so I don't know what I'd do to prevent that. An example run would be
123 the first, 231 the second, 321 and so fourth
What would you use to make a sequence that doesn't repeat numbers
The simplest way to generate your sequence would be to use std::shuffle to re-order a vector containing your desired values:
#include <vector>
#include <algorithm>
#include <random>
#include <iostream>
int main()
{
std::random_device rd;
std::mt19937 g(rd());
std::vector<int> elements = { 1, 2, 3 };
std::shuffle(elements.begin(), elements.end(), g);
for (int i : elements)
{
std::cout << i << "\n";
}
}
If you really must use rand() (its not generally a very good random number generator) you can just about squeeze it into shuffle too:
#include <vector>
#include <algorithm>
#include <ctime>
#include <iostream>
struct RandDevice
{
using result_type = uint32_t;
static result_type max() { return static_cast<result_type>(RAND_MAX); };
static result_type min() { return 0; };
result_type operator()() {
return static_cast<result_type>(rand());
}
};
int main()
{
std::vector<int> elements = { 1, 2, 3 };
srand(time(0));
std::shuffle(elements.begin(), elements.end(), RandDevice());
for (int i : elements)
{
std::cout << i << "\n";
}
}
You can use std::next_permutation
Example here : https://en.cppreference.com/w/cpp/algorithm/next_permutation
it's pretty easy to do.. just compare the number you with every occupied element in the array. if it is not in the array, add to array. else, try again.
I have done similar code check this out
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
void displayArray(int randNum[], int elements);
void randomNum(int randNums[], int elements);
int main ()
{
//declare array
int numbers[999] = {0};
//random number generator
srand(static_cast<int>(time(0)));
randomNum(numbers, 999);
displayArray(numbers, 999);
system("pause");
return 0;
}
void randomNum(int randNums[], int elements)
{
for (int i = 0; i < elements; i++)
{
bool same;
do
{
same = false;
randNums[i] = rand() % 999 + 100;
// Check if the newly generated number is a duplicate:
for (int check = 0; check < i; check++)
{
if (randNums[i] == randNums[check])
{
same = true;
break;
}
}
} while (same);
}
}
void displayArray(int randNum[], int elements)
{
for (int sub = 0; sub < elements; sub ++)
{
cout << "Unique Numbers: " << randNum[sub] << endl;
}
}
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);
}
The number of prime numbers less than 10,000,000 is 664,579 but my code generates only 664,214. The source of the numbers is https://primes.utm.edu/howmany.html
#include <iostream>
#include <bitset>
#include <vector>
using namespace std;
const int N = 10000001;
bitset<N>num;
vector<int>prime;
inline void sieve()
{
num.flip();
num[0] = num[1] = 0;
for(int i=2;i<N;i++)
if(num[i])
{
prime.push_back(i);
for(long long unsigned j=i*i; j<N;j+=i)
num[j] = 0;
}
}
int main() {
sieve();
cout << prime.size() << endl;
return 0;
}
You have an integer overflow when calculating i*i. The fact that you then assign the result to a long long doesn't make the compiler promote the types before the multiplication.
If I declare i as a long long unsigned int then your program outputs 664579
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;
}
}