Monte-carlo simulation of pi in root

In the macro that I have attached below, I am trying to use TRandom3 to generate random numbers and then do the usual monte-carlo simulation of pi. My objective is to try and do that for different values on nTotal in order to see how the approximation of pi improves with increasing number of nTotal. I first tried the code in codeblocks (with C++ way of generating random numbers), and it works totally fine. However, this root macro does not work and gives me the following error:

Error: Illegal initialization of nTotal. Constructor exists montecarlo2.C:6:
*** Interpreter error recovered ***

Could anyone help me understand what I did wrong in initializing nTotal?

montecarlo2.C (629 Bytes)

ROOT Version: 5.10
Platform: Ubuntu


You need ROOT 6 for this feature.

Really? Thatā€™s unfortunate cause I recently switched to Root 5 because of some issues. Any idea how I go about doing it in version 5?

Hi hep_1
I donā€™t know in detail but you mistake ā€œTRandom3 rand(0)ā€.
This ā€œrand(0)ā€ writing is mistake. Maybe root understand rand(0) as C standard function.

I modified your code.
try it again

{
  vector<int> nTotal = {100,1000,10000,100000,1000000};

  int circle_points = 0;
  int square_points = 0;

  TRandom3 rnd;

  for (Int_t i = 0; i < nTotal.size(); i++){
    for (Int_t j = 0; j < nTotal[i]; j++){

      Double_t x = rnd.Rndm();
      Double_t y = rnd.Rndm();

      Double_t  distance = x*x + y*y;

      if (distance <= 1) circle_points++;
      square_points++;

    }
  }
  Double_t pi = double(4*circle_points)/(square_points);
    cout<<pi<<endl;
}

Hi @meu. I donā€™t think the problem is with TRandom3 rand(0) because when I ran the code for just one value of nTotal, letā€™s say nTotal = 1000, it was working fine. Also, the change you made did not work, and it still gives the same error. Thank you, though.

Sorry, I canā€™t help.
I used Root 6. This work good and canā€™t take rand(0).

So, I suggest to change vector to array.
I think Root5 have problem with vector.

{
  int nTotal[5] = {100,1000,10000,100000,1000000};
  int circle_points = 0;
  int square_points = 0;

  TRandom3 rnd(0);

  for (Int_t i = 0; i < 5; i++){
    for (Int_t j = 0; j < nTotal[i]; j++){
    Double_t x = rnd.Rndm();
    Double_t y = rnd.Rndm();

    Double_t  distance = x*x + y*y;

     if (distance <= 1) circle_points++;
     square_points++;
    }
  }
  Double_t pi = double(4*circle_points)/(square_points);
    cout<<pi<<endl;
}

Thank you @meu. I would like to point out that I think it should be TRandom3 rand(0) instead of rnd(0). I also have a follow-up question. So, what you suggested works perfectly fine once I changed rnd to rand. I was playing with your code and tried the following:

{
  int nTotal[6] = {100,1000,10000,100000,1000000,10000000};
  int circle_points = 0;
  int square_points = 0;

  TRandom3 rand(0);

  for (Int_t i = 0; i < 6; i++){
    for (Int_t j = 0; j < nTotal[i]; j++){
    Double_t x = rand.Rndm();
    Double_t y = rand.Rndm();

    Double_t  distance = x*x + y*y;

     if (distance <= 1) circle_points++;
     square_points++;
    }
     Double_t pi = double(4*circle_points)/(square_points);
    cout<<pi<<endl;
  }
 
}

All I did was changed nTotal to have 6 elements instead of 5 and made corresponding changes everywhere. This one does not work, though and gives the error:

Error: Too many initializers, exceeded length of array for ā€˜nTotalā€™ montecarloforum.C:2:
*** Interpreter error recovered ***

Any idea why that would be the case?

In Root 6, grammar is more strict than Root5. So, I think rand(0) work in Root 5 but canā€™t work in Root6.

In follow-up question,I canā€™t see this problem.
I think your code is correct.
I have no idea sorry.

You can use:

  int nTotal[] = {100, 1000, 10000, 100000, 1000000, 10000000};
  // ...
  for (UInt_t i = 0; i < (sizeof(nTotal) / sizeof(nTotal[0])); i++) {

@Wile_E_Coyote, thank you. This works as I wanted it to. Just a small question on the for loop. So why was it necessary to divide the sizeof(nTotal) by sizeof(nTotal[0]). I thought that since sizeof(nTotal[0]) is just 1, removing that part would still allow the code to run fine. Surprisingly, I found that the code does give me six values of pi, and an error at the end saying:

Error: Array index out of range nTotal ā†’ [7] valid upto nTotal[5] montecarloforum2.C:9:

It is not one. It is the same value as sizeof(int) which is 4 (bytes).

1 Like

@pcanal, oh okay. But still not sure why I have to do:

i < (sizeof(nTotal) / sizeof(nTotal[0]))

inside of that loop.