Change value of randomly generated number upon second compilation - c++

I applied the random number generator to my code although the first number generated doesn't change when I run the code second or the third time. The other numbers change however and the issue is only on the first value. I'm using code blocks; Cygwin GCC compiler (c++ 17). Seeding using time.
#include <iostream>
#include <random>
#include <ctime>
int main()
{
std::default_random_engine randomGenerator(time(0));
std::uniform_int_distribution randomNumber(1, 20);
int a, b, c;
a = randomNumber(randomGenerator);
b = randomNumber(randomGenerator);
c = randomNumber(randomGenerator);
std::cout<<a<<std::endl;
std::cout<<b<<std::endl;
std::cout<<c<<std::endl;
return 0;
}
In such a case when I run the code the first time it may produce a result like a = 4, b = 5, c = 9. The second and further time (a) remains 4 but (b) and (c) keep changing.

Per my comment, the std::mt19937 is the main PRNG you should consider. It's the best one provided in <random>. You should also seed it better. Here I use std::random_device.
Some people will moan about how std::random_device falls back to a deterministic seed when a source of true random data can't be found, but that's pretty rare outside of low-level embedded stuff.
#include <iostream>
#include <random>
int main() {
std::mt19937 randomGenerator(std::random_device{}());
std::uniform_int_distribution randomNumber(1, 20);
for (int i = 0; i < 3; ++i) {
std::cout << randomNumber(randomGenerator) << ' ';
}
std::cout << '\n';
return 0;
}
Output:
~/tmp
❯ ./a.out
8 2 16
~/tmp
❯ ./a.out
7 12 14
~/tmp
❯ ./a.out
8 12 4
~/tmp
❯ ./a.out
18 8 7
Here we see four runs that are pretty distinct. Because your range is small, you'll see patterns pop up every now and again. There are other areas of improvement, notably providing a more robust seed to the PRNG, but for a toy program, this suffices.

Related

RNG - getting same results with each repetition (cpp)

My code keeps giving the same results, each for loop repetition always returns same value, which makes scores identical if I try to execute program the same amount of times.
How can I solve my problem?
#include <iostream>
#include <random>
double a=0; //stores instances of a randomized number
double b=0;
double c=0;
double d=0;
int y;
std::random_device rd;
std::uniform_int_distribution<int> dist(0, 3);
void Random(int y){ //function cycles y times and each time gets one value 0-3 and increases a,b,c,d by 1
for(int i=0;i<y;i++){
switch(dist(rd)){ //a(0), b(1), c(2), d(3)
case 0:
a++;
break;
case 1:
b++;
break;
case 2:
c++;
break;
case 3:
d++;
break;
}
}
}
int main(){
std::cin>>y;
std::cout<<'\n';
Random(y); //running function Random
std::cout<<"a: "<<a<<" b: "<<b<<" c: "<<c<<" d: "<<d<<'\n'; //presents how many times we get each value
std::cout<<"a: "<<a/y*100<<"% b: "<<b/y*100<<"% c: "<<c/y*100<<"% d: "<<d/y*100<<"%"; //scores percentage
}
1ST TRY:
1000000
a: 249245 b: 250866 c: 249829 d: 250060
a: 24.9245% b: 25.0866% c: 24.9829% d: 25.006%
Process returned 0 (0x0) execution time : 7.603 s
2ND TRY:
1000000
a: 249245 b: 250866 c: 249829 d: 250060
a: 24.9245% b: 25.0866% c: 24.9829% d: 25.006%
Process returned 0 (0x0) execution time : 4.792 s
You cannot use std::random_device like this. It is only intended for seeding a random engine, and there is no guarantee at all on what comes out of it. In fact one implementation of it (the one in mingw) was just return 4 for some time.
Here is how to use it:
// Initial setup
std::random_device seeder;
std::mt19937_64 generator(seeder());
std::uniform_int_distribution<int> between0and3(0, 3);
// Then use for generating numbers
int x = between0and3(generator);
Do not repeat the initial setup steps, if you need more than one number keep the generator and distribution around for subsequent calls.
If you are indeed using an old version of mingw this will not be enough to solve your issue as seeder() will return the same value everytime. In that case you should upgrade it. If not possible, xor-ing the seed with it some other source of variation - current timer or OS-provided random number could be a workaround.

Method for generating a random bitset of uniform distribution

How can I generate a bitset whose length is a multiple of 8 (corresponding to a standard data type) wherein each bit is 0 or 1 with equal probability?
The following works.
Choose a PRNG with good statistical properties
Seed it well
Generate integers over an inclusive range including the minimum and maximum of the integer type.
Since the integers are uniformly distributed across their entire range, each bit representation must be equally probable. Since all bit representations are present, each bit is equally like to be on or off.
The following code accomplishes this:
#include <cstdint>
#include <iostream>
#include <random>
#include <algorithm>
#include <functional>
#include <bitset>
//Generate the goodness
template<class T>
T uniform_bits(std::mt19937& g){
std::uniform_int_distribution<T> dist(std::numeric_limits<T>::lowest(),std::numeric_limits<T>::max());
return dist( g );
}
int main(){
//std::default_random_engine can be anything, including an engine with short
//periods and bad statistical properties. Rather than cross my finers and pray
//that it'll somehow be okay, I'm going to rely on an engine whose strengths
//and weaknesses I know.
std::mt19937 engine;
//You'll see a lot of people write `engine.seed(std::random_device{}())`. This
//is bad. The Mersenne Twister has an internal state of 624 bytes. A single
//call to std::random_device() will give us 4 bytes: woefully inadequate. The
//following method should be slightly better, though, sadly,
//std::random_device may still return deterministic, poorly distributed
//numbers.
std::uint_fast32_t seed_data[std::mt19937::state_size];
std::random_device r;
std::generate_n(seed_data, std::mt19937::state_size, std::ref(r));
std::seed_seq q(std::begin(seed_data), std::end(seed_data));
engine.seed(q);
//Use bitset to print the numbers for analysis
for(int i=0;i<50000;i++)
std::cout<<std::bitset<64>(uniform_bits<uint64_t>(engine))<<std::endl;
return 0;
}
We can test the output by compiling (g++ -O3 test.cpp) and doing some stats with:
./a.out | sed -E 's/(.)/ \1/g' | sed 's/^ //' | numsum -c | tr " " "\n" | awk '{print $1/25000}' | tr "\n" " "
The result is:
1.00368 1.00788 1.00416 1.0036 0.99224 1.00632 1.00532 0.99336 0.99768 0.99952 0.99424 1.00276 1.00272 0.99636 0.99728 0.99524 0.99464 0.99424 0.99644 1.0076 0.99548 0.99732 1.00348 1.00268 1.00656 0.99748 0.99404 0.99888 0.99832 0.99204 0.99832 1.00196 1.005 0.99796 1.00612 1.00112 0.997 0.99988 0.99396 0.9946 1.00032 0.99824 1.00196 1.00612 0.99372 1.00064 0.99848 1.00008 0.99848 0.9914 1.00008 1.00416 0.99716 1.00868 0.993 1.00468 0.99908 1.003 1.00384 1.00296 1.0034 0.99264 1 1.00036
Since all of the values are "close" to one, we conclude that our mission is accomplished.
Here is a nice function to achieve this:
template<typename T, std::size_t N = sizeof(T) * CHAR_BIT> //CHAR_BIT is 8 on most
//architectures
auto randomBitset() {
std::uniform_int_distribution<int> dis(0, 1);
std::mt19937 mt{ std::random_device{}() };
std::string values;
for (std::size_t i = 0; i < N; ++i)
values += dis(mt) + '0';
return std::bitset<N>{ values };
}

Why is dividing slower than bitshifting in C++?

I wrote two pieces of code, one that divides a random number by two, and one that bitshifts the same random number right once. As I understand it, this should produce the same result. However, when I time both pieces of code, I consistently get data saying that the shifting is faster. Why is that?
Shifting code:
double iterations = atoi(argv[1]) * 1000;
int result = 0;
cout << "Doing " << iterations << " iterations." << endl;
srand(31459);
for(int i=0;i<iterations;i++){
if(i % 2 == 0){
result = result + (rand()>>1);
}else{
result = result - (rand()>>1);
}
}
Dividing code:
double iterations = atoi(argv[1]) * 1000;
int result = 0;
cout << "Doing " << iterations << " iterations." << endl;
srand(31459);
for(int i=0;i<iterations;i++){
if(i % 2 == 0){
result = result + (rand() / 2);
}else{
result = result - (rand() / 2);
}
}
Timing and results:
$ time ./divide 1000000; time ./shift 1000000
Doing 1e+09 iterations.
real 0m12.291s
user 0m12.260s
sys 0m0.021s
Doing 1e+09 iterations.
real 0m12.091s
user 0m12.056s
sys 0m0.019s
$ time ./shift 1000000; time ./divide 1000000
Doing 1e+09 iterations.
real 0m12.083s
user 0m12.028s
sys 0m0.035s
Doing 1e+09 iterations.
real 0m12.198s
user 0m12.158s
sys 0m0.028s
Addtional information:
I am not using any optimizations when compiling
I am running this on a virtualized install of Fedora 20, kernal: 3.12.10-300.fc20.x86_64
It's not; it's slower on the architecture you're running on. It's almost always slower because the hardware behind bit shifting is trivial, while division is a bit of a nightmare. In base 10, what's easier for you, 78358582354 >> 3 or 78358582354 / 85? Instructions generally take the same time to execute regardless of input, and in you case, it's the compiler's job to convert /2 to >>1; the CPU just does as it's told.
It isn't actually slower. I've run your benchmark using nonius like so:
#define NONIUS_RUNNER
#include "Nonius.h++"
#include <type_traits>
#include <random>
#include <vector>
NONIUS_BENCHMARK("Divide", [](nonius::chronometer meter)
{
std::random_device rd;
std::uniform_int_distribution<int> dist(0, 9);
std::vector<int> storage(meter.runs());
meter.measure([&](int i) { storage[i] = storage[i] % 2 == 0 ? storage[i] - (dist(rd) >> 1) : storage[i] + (dist(rd) >> 1); });
})
NONIUS_BENCHMARK("std::string destruction", [](nonius::chronometer meter)
{
std::random_device rd;
std::uniform_int_distribution<int> dist(0, 9);
std::vector<int> storage(meter.runs());
meter.measure([&](int i) { storage[i] = storage[i] % 2 == 0 ? storage[i] - (dist(rd) / 2) : storage[i] + (dist(rd) / 2); });
})
And these are the results:
As you can see both of them are neck and neck.
(You can find the html output here)
P.S: It seems I forgot to rename the second test. My bad.
It seems that difference in resuls is bellow the results spread, so you cann't really tell if it is different. But in general division can't be done in single opperation, bit shift can, so bit shift usualy should be faster.
But as you have literal 2 in your code, I would guess that compiler, even without optimizations produces identical code.
Note that rand returns int and divide int (signed by default) by 2 is not the same as shifting by 1. You can easily check generated asm and see the difference, or simply check resulting binary size:
> g++ -O3 boo.cpp -c -o boo # divide
> g++ -O3 foo.cpp -c -o foo # shift
> ls -la foo boo
... 4016 ... boo # divide
... 3984 ... foo # shift
Now add static_cast patch:
if (i % 2 == 0) {
result = result + (static_cast<unsigned>(rand())/2);
}
else {
result = result - (static_cast<unsigned>(rand())/2);
}
and check the size again:
> g++ -O3 boo.cpp -c -o boo # divide
> g++ -O3 foo.cpp -c -o foo # shift
> ls -la foo boo
... 3984 ... boo # divide
... 3984 ... foo # shift
to be sure you can verify that generated asm in both binaries is the same

Rand() % 14 only generates the values 6 or 13

Whenever I run the following program the returned values are always 6 or 13.
#include <iostream>
#include <fstream>
#include <ctime>
#include <cstdlib>
using namespace std;
//void randomLegs();
//void randomPush();
//void randomPull();
//void randomMisc();
int main(int argc, const char * argv[])
{
srand(time(NULL));
//randomLegs();
cout << rand() % 14;
return 0;
}
I have run the program close to a hundred times during today and yesterday.
Can anyone tell me what I'm doing wrong?
Thank you.
EDIT: By the way, if I change the range of rand() to say 13 or 15 it works just fine.
Per wikipedia, the multiplier being used in Apple's MCG random number generator is 16807. This is divisible by 7, so the first random number produced after srand() will have only one bit of entropy mod 14 (that is, it can only take on two values).
It's a crappy RNG they've got there. An easy solution, though, is just to call rand() a few times right after srand, and discard the results.
I can reproduce the problem on Mac OS X 10.9 with Xcode 5 - it looks like it might actually be a bug, or at least a limitation with rand()/srand() on OS X 10.9.
I recommend you use arc4random() instead, which works a lot better than rand(), and which doesn't require that you randomize the seed:
#include <iostream>
#include <cstdlib>
using namespace std;
int main(int argc, const char * argv[])
{
cout << (arc4random() % 14) << endl;
return 0;
}
Test:
$ g++ -Wall -O3 srand.cpp && ./a.out
5
$ ./a.out
8
$ ./a.out
0
$ ./a.out
8
$ ./a.out
11
$ ./a.out
8
$ ./a.out
3
$ ./a.out
13
$ ./a.out
9
$
rand() % 14 is often a poor random number generator. You'll probably get better results with this
(int)(14*(rand()/(RAND_MAX + 1.0)))

Random Number Generator mechanism

i had the following problem in my book:
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
clrscr();
randomize();
int Game[]={10,16},P;
int Turn=random(2)+5;
for(int T=0;T<20;T++)
{
P=random(2);
cout<<Game[P]+Turn<<"#";
}
getch();
}
The output comes like 16#22#16#16#16#22#....20 times...
Why the output of this always comes either 16# or 22#?? why not 15# or 21#?? i would like to the mechanism of this program. Thanks.
turn=random(2)+5;
if random(2) gives 0 then turn becomes turn=0+5=5 which implies that i should get 10+5=15 and 16+5=21 along with 16 and 22 but i m not getting them.
We got the above question in our computer science theory exam and we were to chose the correct answer(i.e it generates 16 and 22) but how will i am going to know that it will generate only 16 and 22. As i explained above 15 and 21 are also possible..
maybe this helps:
The seed for the random number generator is not set.
If you call srand(time(NULL)) then you will get more random results
C++ rand() gives same number when running process
You need to give a seed value that would help get "really" random. mumbers
A computer cannot randomize numbers by itself, it uses a seed for that.
But seed's aren't completely random they just have a specific order, like:
1
2
8
5
4
These numbers look pretty random but when you run the program the next time you will get:
1
2
8
5
4
The exact same.
To prevent this we use the time as a seed, time always changes so it will always generate new numbers.
#include <time.h>
srand(time(NULL)); // srand is the function to randomize numbers from a seed, we use 'time' as seed here
this video explains it.
Because Turn is only randomized once - at the beginning of the loop. If you move the assignment of Turn into your loop, you should get 15 and 21 also:
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
clrscr();
randomize();
int Game[]={10,16},P;
int Turn;
for(int T=0;T<20;T++)
{
P=random(2);
Turn=random(2)+5;
cout<<Game[P]+Turn<<"#";
}
getch();
}
Also, as said by others, if you want the output to differ between runs, you will need to seed your random number generator, for instance by calling srand() with a seed. For instance:
#include <time.h>
(...)
srand(time(NULL));