From header <random>, there is an engine called std::minstd_rand.
Are the bounds for this engines random numbers inclusive or exclusive? It's got min and max functions, but I specifically want to know whether the random simulation can equal min or max, as opposed to just be bounded by them.
Documentation uses the word "between", which is of course not unambigous.
t's got min and max functions, but I specifically want to know whether the random simulation can equal min or max.
Yes.
From https://en.cppreference.com/w/cpp/numeric/random/linear_congruential_engine#Characteristics (emphasis mine):
min [static]
gets the smallest possible value in the output range
(public static member function)
max [static]
gets the largest possible value in the output range
(public static member function)
I think that we can be a little more precise.
As you can see std::minstd_rand is really std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647> hence the emphasis of my co-answerer.
To simply check that indeed the generator can produce the value returned by min() max() we can use this simpler generator.
std::linear_congruential_engine<std::uint_fast32_t, 3, 0, 5>
If we test it
#include <random>
#include <iostream>
int main()
{
std::linear_congruential_engine<std::uint_fast32_t, 3, 0, 5> gen;
std::cout << (std::uint_fast32_t) std::linear_congruential_engine<std::uint_fast32_t, 3, 0, 5>::min() << std::endl;
std::cout << (std::uint_fast32_t) std::linear_congruential_engine<std::uint_fast32_t, 3, 0, 5>::max() << std::endl<< std::endl;
gen.seed(1);
for (int i = 0; i < 5; i++)
{
std::cout << gen() << std::endl;
}
std::cout << std::endl;
return 0;
}
we get
1
4
3
4
2
1
3
As you can see the generator did hit the min and max. So
min [static] gets the smallest possible value in the output range (public static member function)
max [static] gets the largest possible value in the output range (public static member function)
The generator follows this rule https://en.wikipedia.org/wiki/Linear_congruential_generator .
So basically min() returns 1 and max() returns m-1. No smarter than this.
If I take another generator std::linear_congruential_engine<std::uint_fast32_t, 3, 0, 6>
and test it
#include <random>
#include <iostream>
int main()
{
std::linear_congruential_engine<std::uint_fast32_t, 3, 0, 6> gen;
std::cout << (std::uint_fast32_t) std::linear_congruential_engine<std::uint_fast32_t, 3, 0, 6>::min() << std::endl;
std::cout << (std::uint_fast32_t) std::linear_congruential_engine<std::uint_fast32_t, 3, 0, 6>::max() << std::endl << std::endl;
for (int s = 0; s < 6; s++)
{
gen.seed(1);
for (int i = 0; i < 5; i++)
{
std::cout << gen() << " ";
}
std::cout << std::endl;
}
return 0;
}
the output is
1
5
3 3 3 3 3
3 3 3 3 3
3 3 3 3 3
3 3 3 3 3
3 3 3 3 3
3 3 3 3 3
Whatever the seed the output is always 3. so much for hitting the min and max
To finally answer the question
Are the bounds for this engines random numbers inclusive or exclusive?
I don't know. It depends. And I don't know if somebody has ever proved that for whatever seed, you eventually always hit min and max for the std::minstd_rand generator… But that is more of a mathexchange question...
Related
#include <iostream>
using namespace std;
int main()
{
const int ARRAY_SIZE = 10;
int value[ARRAY_SIZE] = { 1, 2, 3, 4, 3, 4, 2, 3, 5, 6};
int value2[100];
for (int i = 0; i < ARRAY_SIZE; i++)
{
for (int j = i + 1; j <= ARRAY_SIZE; j++)
{
if (value[i] == value[j])
{
cout << value[i] << " ";
}
}
}
return 0;
}
The output is
2 3 3 4 3
How can I make the output become 2 3 4 ?
Edit: I'm trying to print all numbers appearing more than once in the value array
I think I should create one more array to store value, but I stuck with it and don't know how to do it.
It helps considerably to sort your array. Then you only need two indices:
a write index, starting at 0
a read index, starting at 1
Loop over your array using the read index. For every array[read] that has a duplicate value at array[read-1], IFF that value also does not exist at array[write], then copy it over and increment your write index.
Finally, the new length of your data is equal to your write index.
The basic idea is this: if I have a sorted list of values:
1 3 3 4 5 5 5 7 7 9
Then I can easily see if a value is a duplicate or not by comparing the current (read) with the previous.
┌────┐
1 3 3 │4 5│ 5 5 7 7 9 -- not duplicates
└────┘
↑
┌────┐
1 3 3 4 │5 5│ 5 7 7 9 -- duplicate values
└────┘
↑
The only remaining trick is to make just a single copy of that value to the write index, which we can do by simply looking at the last thing we wrote.
You can use a std::map to count the number of times a value is in the array. If the number appears 2 or more times, then print it.
#include <iostream>
#include <map>
int main()
{
const int ARRAY_SIZE = 10;
int value[ARRAY_SIZE] = { 1, 2, 3, 4, 3, 4, 2, 3, 5, 6};
std::map <int, int> mp;
for(int i : value)
++mp[i];
for(const auto& p : mp)
if(p.second > 1)
std::cout << p.first << ' ';
}
Link.
I'm trying to randomly generate a double round-robin schedule for several teams, with teams as lines and rounds as columns. Each team is scheduled against every other team twice, once assigned positive value of the oppoent for a match at home, once negative value for a match away.
The code will be kinda like below, except it should work for a 2D array instead of 1D, where certain "K" and "-K" is taken off from possible randomized value of element(team, round) for each line of a 2D array, instead of a fixed value.
K is the #line that makes sure a team does not match itself (eg. make k=+-2's weight=0 in "dist{}" while assigning line #2, so "2" and "-2" will not occur as team 2's assigned opponent for itself, home or away), but this removal should NOT be permanent, since in other lines of the schedule array the team #K is a valid opponent.
Is there a functionality that allows taking a different k off the randomization for each line(team)? Or could I do it with srand()?
#include <functional>
#include <iostream>
#include <ostream>
#include <random>
int main()
{
std::random_device rd;
unsigned long seed = rd();
std::cout << "seed " << seed << std::endl;
std::mt19937 engine(seed);
// Distribution {0, 1, 2, 4, 5}
std::discrete_distribution<> dist {{1, 1, 1, 0, 1, 1}}; // 3 given 0 weight(chance).
auto rng = std::bind(dist, std::ref(engine));
const int n = 10;
for (int i = 0; i != n; ++i)
{
int x = rng();
std::cout << x << std::endl;
}
return 0;
}
I think you want this one
std::discrete_distribution<> make_dist(int k, int N)
{
std::vector<int> dist(N,1);
dist.at(k) = 0;
return std::discrete_distribution<>(dist.begin(), dist.end());
}
replace your
std::discrete_distribution<> dist {{1, 1, 1, 0, 1, 1}}; // 3 given 0 weight(chance).
with
auto dist = make_dist(3,6);
I know this might be a pretty stupid question to ask, but what the hell..
I at the moment trying to implement soft max action selector, which uses the boltzmann distribution.
Formula
What I am bit unsure about, is how how do known if you want to use a specific action?
I mean the function provides me with a probability?, but how do I use that to select which action I want to perform?
For some machine learning applications, there is a point where a set of raw outputs (like from a neural network) needs to be mapped to a set of probabilities, normalized to sum to 1.
In reenforcement learning, a set of available actions' weights might need to be mapped to a set of associated probabilities, which will then by used to randomly select the next action taken.
The Softmax function is commonly used to map output weights to a set of corresponding probabilities. A "temperature" parameter allows the selection policy to be tuned, interpolating between pure exploitation (a "greedy" policy, where the highest-weighted action is always chosen) and pure exploration (where each action has an equal probability of being chosen).
This is a simple example of using the Softmax function. Each "action" corresponds to one indexed entry in the vector<double> objects passed around in this code.
#include <iostream>
#include <iomanip>
#include <vector>
#include <random>
#include <cmath>
using std::vector;
// The temperature parameter here might be 1/temperature seen elsewhere.
// Here, lower temperatures move the highest-weighted output
// toward a probability of 1.0.
// And higer temperatures tend to even out all the probabilities,
// toward 1/<entry count>.
// temperature's range is between 0 and +Infinity (excluding these
// two extremes).
vector<double> Softmax(const vector<double>& weights, double temperature) {
vector<double> probs;
double sum = 0;
for(auto weight : weights) {
double pr = std::exp(weight/temperature);
sum += pr;
probs.push_back(pr);
}
for(auto& pr : probs) {
pr /= sum;
}
return probs;
}
// Rng class encapsulates random number generation
// of double values uniformly distributed between 0 and 1,
// in case you need to replace std's <random> with something else.
struct Rng {
std::mt19937 engine;
std::uniform_real_distribution<double> distribution;
Rng() : distribution(0,1) {
std::random_device rd;
engine.seed(rd());
}
double operator ()() {
return distribution(engine);
}
};
// Selects one index out of a vector of probabilities, "probs"
// The sum of all elements in "probs" must be 1.
vector<double>::size_type StochasticSelection(const vector<double>& probs) {
// The unit interval is divided into sub-intervals, one for each
// entry in "probs". Each sub-interval's size is proportional
// to its corresponding probability.
// You can imagine a roulette wheel divided into differently-sized
// slots for each entry. An entry's slot size is proportional to
// its probability and all the entries' slots combine to fill
// the entire roulette wheel.
// The roulette "ball"'s final location on the wheel is determined
// by generating a (pseudo)random value between 0 and 1.
// Then a linear search finds the entry whose sub-interval contains
// this value. Finally, the selected entry's index is returned.
static Rng rng;
const double point = rng();
double cur_cutoff = 0;
for(vector<double>::size_type i=0; i<probs.size()-1; ++i) {
cur_cutoff += probs[i];
if(point < cur_cutoff) return i;
}
return probs.size()-1;
}
void DumpSelections(const vector<double>& probs, int sample_count) {
for(int i=0; i<sample_count; ++i) {
auto selection = StochasticSelection(probs);
std::cout << " " << selection;
}
std::cout << '\n';
}
void DumpDist(const vector<double>& probs) {
auto flags = std::cout.flags();
std::cout.precision(2);
for(vector<double>::size_type i=0; i<probs.size(); ++i) {
if(i) std::cout << " ";
std::cout << std::setw(2) << i << ':' << std::setw(8) << probs[i];
}
std::cout.flags(flags);
std::cout << '\n';
}
int main() {
vector<double> weights = {1.0, 2, 6, -2.5, 0};
std::cout << "Original weights:\n";
for(vector<double>::size_type i=0; i<weights.size(); ++i) {
std::cout << " " << i << ':' << weights[i];
}
std::cout << "\n\nSoftmax mappings for different temperatures:\n";
auto softmax_thalf = Softmax(weights, 0.5);
auto softmax_t1 = Softmax(weights, 1);
auto softmax_t2 = Softmax(weights, 2);
auto softmax_t10 = Softmax(weights, 10);
std::cout << "[Temp 1/2] ";
DumpDist(softmax_thalf);
std::cout << "[Temp 1] ";
DumpDist(softmax_t1);
std::cout << "[Temp 2] ";
DumpDist(softmax_t2);
std::cout << "[Temp 10] ";
DumpDist(softmax_t10);
std::cout << "\nSelections from softmax_t1:\n";
DumpSelections(softmax_t1, 20);
std::cout << "\nSelections from softmax_t2:\n";
DumpSelections(softmax_t2, 20);
std::cout << "\nSelections from softmax_t10:\n";
DumpSelections(softmax_t10, 20);
}
Here is an example of the output:
Original weights:
0:1 1:2 2:6 3:-2.5 4:0
Softmax mappings for different temperatures:
[Temp 1/2] 0: 4.5e-05 1: 0.00034 2: 1 3: 4.1e-08 4: 6.1e-06
[Temp 1] 0: 0.0066 1: 0.018 2: 0.97 3: 0.0002 4: 0.0024
[Temp 2] 0: 0.064 1: 0.11 2: 0.78 3: 0.011 4: 0.039
[Temp 10] 0: 0.19 1: 0.21 2: 0.31 3: 0.13 4: 0.17
Selections from softmax_t1:
2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1
Selections from softmax_t2:
2 2 2 2 2 2 1 2 2 1 2 2 2 1 2 2 2 2 2 1
Selections from softmax_t10:
0 0 4 1 2 2 2 0 0 1 3 4 2 2 4 3 2 1 0 1
I'm trying to make a recursive program that sums an array or a list of numbers.
Using visual studio 2013, C++ console application.
My 1st question is:
Now I know how many numbers I have and I know the size of my array. How can I program it the way that don't know the numbers in advance, like while it's calculating the numbers there are still new numbers adding up, with the least space usage?
My 2nd question is that:
How can i improve the program that still works recursively and its time and space usage be optimal?
Here is my code:
// summing a list of number.cpp
#include "stdafx.h"
#include "iostream"
int array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sum = 0, i = 0;
int sumarray(int i){
if (i < 9){
sum += array[i];
i++;
sumarray(i);
}
else
return sum;
}
int main(){
std::cout << "sum is ::: " << sumarray(i);
getchar();
}
I hope you'll stop writing functions that depend on global variables to work when they can be easily made to work only with the input they have been provided.
Here's a version that works for me.
#include <iostream>
int sumarray(int array[], int i)
{
if ( i <= 0 )
{
return 0;
}
return sumarray(array, i-1) + array[i-1];
}
int main()
{
int array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
std::cout << "sum is : " << sumarray(array, 0) << std::endl;
std::cout << "sum is : " << sumarray(array, 5) << std::endl;
std::cout << "sum is : " << sumarray(array, 10) << std::endl;
}
Output:
sum is : 0
sum is : 15
sum is : 55
If i >= 9, your function does a return sum;.
(that is fine and good)
Where does your function return if i < 9???
if (i < 9){
sum += array[i];
i++;
sumarray(i); // I see no return statement here!!
}
Basically, if you call sumarray(3), there is no return statement that gets hit.
In your program, there is a global variable called i.
There is also a local parameter to the function also called i.
The local variable shadows the global variable, so there is no clear purpose to the global i.
I'd do it like this:
int array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Pass in the current index, and the size of the array
int sumarray(int i, int sz)
{
if (sz == 0)
{
return 0;
}
return array[i] + sumarray(i+1, sz-1);
}
int main(){
std::cout << "sum is ::: " << sumarray(0, 10);
// Start at the beginning (index 0)
// Run for 10 elements.
getchar();
}
The first recursive call will be to sumarray(1,9); then to sumarray(2,8);... when finally sumarray(10,0) is called, it will return 0.
A function to sum the elements of an array would normally accept the array as an argument. In that case, as a practical matter it must also accept the size of the array. Something like this:
int sumarray(int a[], size_t size) {
A signature like that furthermore gives you access to better recursive approaches. In particular, you could recursively compute the sum of the first and second halves of the array, and return their sum:
size_t midpoint = size / 2;
return sumarray(a, midpoint) + summaray(a + midpoint, size - midpoint);
That's not a complete solution: you need a termination condition (when size is less than 2). Putting that in and finishing off the function are left as an exercise for you, since you'll learn better if you have to put some work into it yourself.
That approach limits the recursion depth and thus stack size (memory overhead) to be proportional to the logarithm of the array size, though it still involves total numbers of function calls and integer additions proportional to the array size. I don't think you can achieve better asymptotic space or time complexity with a recursive algorithm. (A non-recursive algorithm for this task requires only a fixed number of function calls and and a fixed amount of memory overhead, however.)
here is a working C++ code in Qt, which i wrote - Good Luck
I added some debug points outputs to make its understanding clearer
#include <QCoreApplication>
#include <QDebug>
int sum=0;
int sumrec(int *array,int n)
{
if (n>=0)
{
int element=*(array+n); // note *(array+n) -> moving the pointer
// *array+n -> this is adding n to the pointer data (wrong)
// what is array ?
qDebug() << " element value " << *(array+n) << " at n=" << n << " array address = " << array;
n--;
sum=sum+element;
qDebug() << "sum = " << sum;
sumrec(array,n);
return sum;
}
else
{
return 0;
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int A[10]={12,13,14,15,16,17,18,19,20,11};
int b=sumrec(&A[0],9);
qDebug() << "answer = " << b;
//return a.exec();
}
here is the output of the terminal
element value 11 at n= 9 array address = 0x7fff5fbffb78
sum = 11
element value 20 at n= 8 array address = 0x7fff5fbffb78
sum = 31
element value 19 at n= 7 array address = 0x7fff5fbffb78
sum = 50
element value 18 at n= 6 array address = 0x7fff5fbffb78
sum = 68
element value 17 at n= 5 array address = 0x7fff5fbffb78
sum = 85
element value 16 at n= 4 array address = 0x7fff5fbffb78
sum = 101
element value 15 at n= 3 array address = 0x7fff5fbffb78
sum = 116
element value 14 at n= 2 array address = 0x7fff5fbffb78
sum = 130
element value 13 at n= 1 array address = 0x7fff5fbffb78
sum = 143
element value 12 at n= 0 array address = 0x7fff5fbffb78
sum = 155
answer = 155
In C++ you have all the tools to do that in a very simple, readable and safe way. Check out the valarray container:
#include <iostream>
#include <valarray>
int main () {
std::valarray<int> array{1,2,3,4,5,6,7,8,9,10};
std::cout << array.sum() << '\n';
return 0;
}
I'm using rand() for two ints, between 0 and 2. It appears that the first int is never 0 while the second int is 2. Here is my test code-
#include <iostream>
#include <time.h>
int main()
{
srand(time(NULL));
int number1, number2;
number1 = rand() % 3;
number2 = rand() % 3;
printf("%i, %i", number1, number2);
return 0;
}
Output-25 tries
2, 2
2, 2
2, 1
1, 2
0, 1
2, 2
1, 2
1, 0
2, 1
1, 0
0, 0
1, 2
2, 2
0, 0
2, 1
1, 0
2, 2
1, 0
2, 1
1, 0
0, 1
1, 2
1, 0
0, 0
2, 2
As you can see, out of 25 tries, the combo was never 0, 2. Is this the sign that I should probably move over to < random >? In addition, there is never 2, 0.
No, this will happen for 9*(1-1/9)^25 = 0.4736 of all seeds, or roughly 50% of the time. That is, some two digit sequence with digits in {0,1,2} will be missing from your first 25 results roughly half the times you run your program.
Run it again and see what happens.
You should definitely use <random>. The sooner you forget about rand's existence, the happier you will be.
rand is sometimes implemented with a linear congruential generator (LCG). LCGs suffer from a number of defects, the most relevant being that that the low-order bits of sequentially generated numbers are highly correlated. For this reason, you should never use rand() % k to generate numbers in the range [0, k). There are other reasons. In fact, generating unbiased random integers from a restricted range involves some subtleties, which <random> handles for you.
srand(time(NULL)) seeds the random number generator to the current time in seconds from epoch, which means that if you run the program several times in sequence, the seeds will be either the same or similar. If the seeds are the same, the random number sequence will also be the same. If the seeds are similar, the random number sequences may also be similar. So don't do this except in long-running programs. Finding a good seed for a pseudo random number generator can be tricky. <random> implementations will have better default behaviour, so you won't normally need to worry about this.
Taking % 3 does not depend on just lower order bits.
I ran the program below using VC++ simulating running the OP's program ten million times with one second between invocations. It shows no bias.
start = 1413167398
(0, 0) 1110545
(0, 1) 1111285
(0, 2) 1111611
(1, 0) 1111317
(1, 1) 1111666
(1, 2) 1110451
(2, 0) 1111580
(2, 1) 1110491
(2, 2) 1111054
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <map>
#include <utility>
int main()
{
std::map<std::pair<int, int>, int> counter;
unsigned int start = static_cast<unsigned int>(std::time(nullptr));
std::cout << "start = " << start << std::endl;
unsigned int finish = start + 10000000;
for (unsigned int seed = start; seed != finish; ++seed)
{
std::srand(seed);
int x = rand() % 3;
int y = rand() % 3;
++counter[std::make_pair(x, y)];
}
for (auto iter = counter.cbegin(); iter != counter.cend(); ++iter)
{
std::cout << "(" << iter->first.first << ", " << iter->first.second << ") ";
std::cout << iter->second << std::endl;
}
return 0;
}
It is. This code gave me 0,2 pair just at first run:
for( int i = 0; i < 20; ++i) {
number1 = rand() % 3;
number2 = rand() % 3;
printf("%i, %i\n", number1, number2);
}
Generating truly random number from uniform distribution doesn't guarantee that given (possible) number will appear in limited number of trials. The K2 out of four BSI criteria of good PRNG is
K2 — A sequence of numbers which is indistinguishable from 'true
random' numbers according to specified statistical tests.
thus generating pseudo random numbers ofcourse tends to behave in the same way as sampling from true random distribution - though because of limitations any (possible) number will appear at some point (at time less or equal its period).
http://ideone.com/c5oRQL
Use std::uniform_int_distribution
Apart from the above rand() is not the best generator. It introduces bias always whenever the divisor in modulo operation doesn't evenly divides the range of PRNG. Operator % makes the probability distribution produced in this way skewed because RAND_MAX which is maximum value for rand() can be not equal to k * 3 + 2. If divisor not evenly divides the range then distribution will be skewed and the bias increases with divisor. You can read here more on this. Summing it up: in C++ you should use <random> library:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 gen( rd());
std::uniform_int_distribution<> dis( 0, 2);
for ( int n = 0; n < 25; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
}