"Repeating numbers in random number generator (TRandom3( ))


Hello,

I have recently noticed that TRandom3( ) gives repeating numbers. By this, I mean that when I am trying to generate data for a given probability distribution function, for a small number of events, such as 4e6, I get about 150 instances of exactly the same random number being generated (meaning there are 150 pairs of numbers). The exact values of these numbers are subject to change for different seeds, but nevertheless I consistently see about 150 instances of “repeating numbers”. My first guess was that this was a precision issue, but writing out at least 30 significant figures revealed these “repeating numbers” were identical to these large number of decimal places. I wanted to know if there is any mistake in my code. The code is as follows. The first function generates random numbers under the given distribution and the second function counts how many number are repeated.

Thanks,
Mojtaba.

#define _USE_MATH_DEFINES
#include <cmath>
#include <cstdlib>
#include <fstream>
#include <iostream>

// Root libraries
#include "TRandom3.h"
#include <TFile.h>
#include <TH1D.h>
#include <TTree.h>
#include <fstream> 
#include <iostream> 
#include <math.h>
#include <string>
#include <iomanip>
#include <vector>
#include <cstdlib>
#include <sstream>
#include <algorithm>

using namespace std;

Double_t w(double x)
{
	Double_t E=M_E;
	Double_t Pi=M_PI;
	Double_t value=(1. - cos(Pi/8. + x/10.)/pow(E,x/500.))/pow(E,x/1000.);
    return value;
}
void tmgn() {
  cout.precision(24);
  Double_t x, y;
  TFile *fileout = new TFile("5dfnctn15.root", "RECREATE");
  TTree *Tout= new TTree("Tout", "timegen");
  Tout->Branch("time",&x,"x/D");
  Int_t nBins = 300;
  Double_t xMin = 0.0;
  Double_t xMax = 1500.0;
  gRandom = new TRandom3(0);
  //TRandom3 rand(0);
 
 
  Int_t nEvents = 1e6;
  ofstream myconf;
  myconf.precision(30);
  Int_t i;
  myconf.open("5dfnctn15.dat",ios::trunc);
  Int_t counter=0;
  for (i = 0; i < nEvents; i++) {
    Double_t ceiling, test, prob;
    ceiling =2.0001;
    test = 1.;
    prob = 0.;
    while (test > prob) {
      //x = xMin + (xMax - xMin) * rand.Rndm();
      x = xMin + (xMax - xMin) * gRandom->Uniform(1.0);
      y = w(x);
      prob = (double)y / (double) ceiling;
      test = gRandom->Uniform(1.0);
     // test = rand.Rndm();
      counter+=1;
    }
    Tout->Fill();
    myconf<<x<<endl;
  }
  fileout->Write();
  fileout->Close();
  cout<<"Out of"<<"  "<<counter<<"  "<<"events,"<<"  "<<nEvents<<"  "<<"were accepted"<<endl;
}

void repeatnum(){
	ifstream fin;
	fin.open("5dfnctn17.dat");
	
	Double_t number;
	Int_t count=0;
    vector<Double_t> mtrx;
	while(fin >> number){
		mtrx.push_back(number);
	}
	std::sort (mtrx.begin(), mtrx.end());
	const Int_t nevents = mtrx.size();
	for (Int_t i=0;i<nevents; i++) {
		if(mtrx[i+1]==mtrx[i]){
			count+=1;
		}
	}
	cout<<"There are"<<" "<<count<<" "<<"repeating numbers"<<endl;
}

Repeatpost.C (1.9 KB)

ROOT Version: 6.15/01
Platform: macosx64
Compiler: gcc 4.2.1


Hi,

In the file I uploaded the name of the data file in second function did not match with that of data file generated in first function. Now I fixed it, could you please run the new code?

Thanks,
MojtabaRepeatpost.C (1.9 KB)

Yes, around 150 values appear two times.

The TRandom class reference explicitly says that the TRandom3 generator provides “only random number with 32 bits random” (and you would probably need something like 53 bits for really diverse random “double” values).

Try the TRandomMT64 generator (just be aware that, in the current ROOT 6 versions, using the seed = 0 does NOT make it “really” random, as is in the case of the TRandom3 generator).

See also this thread (“TRandom3, problem of repetition?”) and this video (“rand() Considered Harmful”) and the <random> header reference.

1 Like

Hi,

I would suggest to try using TRandomMixmax17, which, when initialised with a different seed, you are guaranteed to have a different sequence of numbers.
If you want to have every time a different seed you could do something like this:

TRandom3 r(0); 
Uint_t IMAX = 4294967295;    // 2^32 -1 
// generate a 64 bits random  seed 
ULong_t seed =  ( (ULong_t) r.Integer(IMAX) << 32 | r.Integer(IMAX) );
gRandom = new TRandomMixMax17(seed); 

If you still observe repeating numbers, please let me know

Cheers

Lorenzo

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.