too many collisions in random number generator collision test - c++

I'm expecting lKolizji variable to be around 128, but it's much higher for large ammount of generated numbers and "boxes". The results for smaller numbers are good. I have no idea why is this happening. Here is my code with example parameters that give wrong answer. Example of good result(around 128) is int lPrzedzialow=1000000;
int iLiczb = 16000;
#include <iostream>
#include <gsl/gsl_rng.h>
#include <stdlib.h>
#include<cmath>
#include <algorithm>
using namespace std;
int main (void)
{
//Random number
unsigned int seed=2596524;
gsl_rng * r=gsl_rng_alloc (gsl_rng_mt19937);
gsl_rng_set(r,seed);
gsl_rng_env_setup();
//Parameters
int lPrzedzialow=10000000000;//number of boxes
int iLiczb = 1600000;//number of random numbers
int z,lKolizji=0;//lKolizji holds collision number
vector<int> lwKomorkach(iLiczb);//number of boxes of random numbers
long double dlPrzedzialu=1./(lPrzedzialow);
//number of box of a random number
for (int i = 0; i < iLiczb; i++)
{
lwKomorkach[i] = floor((gsl_rng_uniform (r)/dlPrzedzialu));
}
//sorting
sort( lwKomorkach.begin(), lwKomorkach.end() );
//how many collisions
for(z=0;z<=iLiczb-1;z++)
{
if(lwKomorkach[z+1]==lwKomorkach[z]){lKolizji++;}
}
double pdf[lKolizji];
pdf[0]=exp(-128);
double spdf=exp(-128);
for(int h=1;h<lKolizji;h++){
pdf[h]=pdf[h-1]*128./(h);
spdf+=pdf[h];
}
double pwyzsze=1.-spdf;
cout<<endl<<lKolizji<<" "<<spdf<<" "<<pwyzsze<<endl;
gsl_rng_free (r);
return 0;
}

This number: 10000000000, is too big for a 32 bit int. In fact, it is equivalent to 1,410,065,408, approx 1/7th of the size you believe it to be.

Related

Adding together two arrays and print into third array

Before I start I must notice that I am a begginer in C++.
I have a code (see below), In this code I have two arrays with 10 random numbers but In tab_A numbers are the same like in tab_B - I don't know how to solve this. Also I don't know how to merge/add/sum these two arrays in new array tab_C and print result.
#include <iostream>
#include <cstdio>
#include <time.h>
#include <cstdlib>
using namespace std;
int gen() {
return rand() % 11;
}
int main()
{
int tab_A[10];
cout<<"TABLICA A DEBUG"<<endl;
srand (time(NULL));
for (int i=0; i<10; i++)
{
tab_A[i] = gen();
cout<<tab_A[i]<<endl;
}
int tab_B[10];
cout<<"TABLICA B DEBUG"<<endl;
srand (time(NULL));
for (int i=0; i<10; i++)
{
tab_B[i] = gen();
cout<<tab_B[i]<<endl;
}
int tab_C[10];
cout<<"TABLICA C DEBUG"<<endl;
int sumAB=0;
sumAB=tab_A[10]+tab_B[10];
tab_C[10]=sumAB;
cout<<tab_C[10]<<endl;
return 0;
}
In the code, you have called srand twice with the same seed. Hence, the numbers that will be randomly generated will be the same. If you want to generate random numbers it is advisable to set seed only once.
Also, there seems to be an issue in the code. C++ has 0-indexing. Hence, the lines
sumAB=tab_A[10]+tab_B[10];
tab_C[10]=sumAB;
cout<<tab_C[10]<<endl;
will give errors.
As the size of tab_C is 10 so the index of the last element would be 9.

How can I make code more time-efficient that calculates 1's in binary representation of int?

I wrote this code for a problem that asks me to calculate the number of 1's in a binary representation of an integer number, and then find the next number which has the same exact number of 1's in its binary number.
I wrote code and it seemed to work just fine until the OJ gives an error:
time limit exceeded error.
I'd like some idea about how I could avoid this error.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int binary(int num){
int count=0;
vector <int> vec;
while(num!=0){
int rem=num%2;
num/=2;
vec.push_back(rem);
}
reverse(vec.begin(),vec.end());
for(int i=0;i<vec.size();i++){
if(vec[i]==1){
count++;
}
}
return count;
}
int main()
{
int looper,order=1;
cin>>looper;
while(looper--){
int num;
cin>>num;
int x=binary(num);
int next_num=num+1;
while(binary(next_num)!=x){
next_num++;
}
cout<<"Case "<<order<<": "<<next_num<<endl;
order++;
}
return 0;
}
This:
int next_num=num+1;
while(binary(next_num)!=x){
next_num++;
}
Is extremely inefficient. Consider your number is
1010101.....01111
Then the next bigger number with same number of 1s is
1010101.....11110
I'll leave it to you to realize the general pattern, the point is just that you dont need a loop to convert all numbers to binary and count the 1s. Instead you can directly construct the number in binary.
PS: std::bitset can come in handy when you need to get the binary representation.
You don't need to count 1's if you're just finding next number that has same numbers of 1's
You just need to swap 1 & 0 from right to left for once.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int binary(int num){
int count=0;
vector <int> vec;
while(num!=0){
int rem=num%2;
num/=2;
vec.push_back(rem);
}
reverse(vec.begin(),vec.end());
for(int i=0;i<vec.size();i++){
while(vec[0]!=vec[i]){
swap(vec[0],vec[i]);
}
// convert binary to decimal
// count = decimal number
return count;
}
int main()
{
int looper,order=1;
cin>>looper;
while(looper--){
int num;
cin>>num;
int x=binary(num);
cout<<"Case "<<order<<": "<<x<<endl;
order++;
}
return 0;
}

c++ calculation of long doubles giving inf or zero

so I created a program that takes in two long double numbers and some a particular form of calculation on them. but the issue is, the output for me is inf or in some compilers, 0..
So the error only occurs when I enter exponential values like say I enter 1.11224e+2121 1.11224e+2121
then I get inf or 0 but if I get something like 2.4 5.9 I get proper value. How do I fix this?
here is my code
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
int main()
{
long double a,b,add=0,mean=0;
cin>>a>>b;
vector<long double> vector;
vector.push_back(a);
vector.push_back(b);
mean=(vector[0]+vector[1])/2;
for (int k = 0; k < 2; k++)
{
add= add+ pow((vector[k] - mean), 2);
}
cout<<add/2;
return 0;
}

Why doesn't my code generate the prime numbers correctly

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

Filling an array with random numbers from 1 to 10^10 in C or C++

a part of an assignment of mine is based on an array (its size is given by the user) which contains random numbers from 1 to 10^10. Then we have to find the k-th smaller number of the array. Here's what I tried:
#include <cstdlib>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <time.h>
using namespace std;
void swap(int *x,int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
int choose_pivot(int i,int j )
{
return((i+j) /2);
}
// Print array
void printarr(int arr[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%d\t",arr[i]);
}
// Find algorithm
int find1(int arr[],int left,int right,int k)
{
int i,j,pivot;
if (left==right)
return arr[left];
else
{
i=left;
j=right+1;
pivot= arr[left];
do
{
do {
i=i+1;
} while (arr[i]>=pivot);
do {
j =j-1;
} while (arr[j]<=pivot);
if (i<j)
swap(arr[i],arr[j]);
} while (j<=i);
}
swap(arr[left],arr[j]);
if (k==j)
return arr[j];
else if (k<j)
find1(arr,left,j-1,k);
else
find1(arr,j+1,right,k-j);
}
int main(int argc, char *argv[])
{
srand(time(NULL));
int n,i,fi,k;
printf("Give array's size:\n");
scanf("%d",&n);
int pin[n];
for (i=0;i<n;i++)
pin[i]=((rand()*rand()) % 1000000000) +1;
printf("Give k: \n");
scanf("%d",&k);
printf("The array contains the following numbers:\n\n");
printarr(pin,n);
fi=find1(pin,0,n-1,k);//find the k-th smallest number in the array
printf("The k-th smallest number is: %d",fi);
system("PAUSE");
}
As you can see 10^10 is a very big value, and I did something else to fill the array with the random numbers. Is it correct? Is there something else I could do?
And my second problem is on the find algorithm. It doesn't work. Could anyone help me with these? Thank you very much
long long get_big_rand()
{
long long result;
do {
result = (rand() & 0x3ff);
result <<= 12;
result |= (rand() & 0xfff);
result <<= 12;
result |= (rand() & 0xfff);
} while (++result > 10000000000ULL);
return result;
}
rand()*rand() is a lot different than a single rand(), it decreases the randomness and changes its distribution. See this question for a deeper explanation.
Also, an integer usually is 4 bytes. It can contain a value as big as 2^31 (2 billions and something) or 2^32 (4 billions and more) if it's unsigned. You can see the max number it can contain checking the INT_MAX macro defined in limits.h. 10^10 is 10 billions, it won't fit in an integer, you'll have to use a bigger type (long long usually is 64 bytes thus more than you need).
rand, also, returns numbers up to RAND_MAX, and since it returns an int, it won't bigger than INT_MAX. You should use some other way to generate a number as big as 10^10.
If you don't care about randomness and random number distributions you could sum n random numbers (obtained by rand) so that n=10^10 / RAND_MAX.
If you take a closer look at 1010 you will notice that it's quite a round limit. My take on this would be to generate each number, one digit at a time and ignoring insignificant zeroes. At this point you would have a number between 0 and 1010-1 inclusive. All you're left with doing is adding a 1.
As for random()*random(), that is the exact topic of this other question.
Alin
Problem #1, an int will only hold a number of size 2^31 in size. You'll need a slightly bigger alternative for your pin array.
Also, multiplying your two random numbers together really doesn't do much - except perhaps make the number less random.
Next, you can't create an array on the stack dynamically with the user's input. That will require a new solution to make alloc an array for you.
rand()*rand() isn't going to do anything for you. It doesn't scale the way you think it does, and it does change the distribuon. In fact
double norm_rand(){
double r=0;
for(unsigned i=0;i!=12;++i)
r+=rand()/static_cast<double>(RAND_MAX);
return (r/12)-6;
}
is a common way to simulate a normal distribution with mean 0 and variance 1;
The best way to to get large random numbers is using a random number device, like /dev/urandom or RtlGenRandom.
i.e.
typedef unsigned long long big_type;
std::vector<double> rnums;
std::vector<big_type> buf(numtoread);
std::ifstream rnds("/dev/urandom");
rnds.read(reinterpret_cast<char*>(&buf[0],buf.size()*sizeof(big_type));
std::transform(buf.begin(),buf.end(),std::back_inserter(rnums),
[](big_type const& i){
return (i*100000000000.)/(std::numeric_limits<big_type>::max());
});
At the risk of doing your homework for you, an entirely different approach is to use the libraries that come with C++.
#include <cassert>
#include <sstream>
#ifndef _MSC_VER //then assume Linux
#include <tr1/random>
#else
#include <random>
#endif
#include <boost/lexical_cast.hpp>
#include <algorithm>
#include <iterator>
#include <iostream>
int main(int argc, char** argv)
{
assert(argc==3);
unsigned const numentries=boost::lexical_cast<unsigned>(argv[1]);
unsigned const k=boost::lexical_cast<unsigned>(argv[2]);
std::cout<<" finding "<<k<<"th of "<< numentries<<" entries\n";
assert(k<=numentries);
std::vector<double> nums(numentries);
std::tr1::uniform_real<> rng(0.,10000000000.);
std::tr1::minstd_rand generator(42u);
std::tr1::variate_generator<std::tr1::minstd_rand, std::tr1::uniform_real<> >
uni(generator, rng);
std::generate_n(nums.begin(),nums.size(),uni);
std::cout<<" Generated:\t ";
std::copy(nums.begin(),nums.end(),std::ostream_iterator<double>(std::cout,"\t"));
std::sort(nums.begin(),nums.end());
std::cout<<"\n The "<<k<<"th smallest entry is "<<nums[k]<<"\n";
return 0;
}
(If you are in class at the level of just asking for making an array of rand numbers and you hand that in, they'll probably fail you)
What I do in practice is to combine the two approaches. This is used in place of the linear conguentual rng used above (the minstd_rand):
template<typename bigtype=unsigned>
struct randeng {
typedef bigtype result_type;
randeng(unsigned x) :
m_samplesrequired(x), m_samples(x), m_lastused() {
std::ifstream rand;
rand.open("/dev/urandom");
assert(rand);
rand.read(reinterpret_cast<char*> (&*(m_samples.begin())),
m_samplesrequired * sizeof(unsigned));
}
result_type operator()() const {
assert(m_lastused<m_samplesrequired);
return m_samples[m_lastused++];
}
result_type max() const {
return std::numeric_limits<result_type>::max();
}
result_type min() const {
return 0;
}
unsigned m_samplesrequired;
std::vector<result_type> m_samples;
mutable unsigned m_lastused;
};
This always seems to give much better results.
you forgot your return statements. at the end of find1 you should be doing:
if (k==j)
return arr[j];
else if (k<j)
return find1(arr,left,j-1,k);
else
return find1(arr,j+1,right,k-j);
}