16.1 Random Number Generation
Table of Contents
TRandom
ROOT provides several random number generators, and the base interface for them is the class TRandom. For a beginner, the most important point is that TRandom is a general-purpose generator that you can use through a single global object called gRandom. You will typically not create TRandom by hand in simple scripts. Instead, you call methods on gRandom to get random values.
A TRandom object produces uniform random numbers between 0 and 1, and also numbers following common probability distributions. Every generator has an internal state controlled by a seed. If two runs start from the same seed and use the same sequence of calls, they produce exactly the same sequence of random numbers.
For reproducible simulations, always set an explicit seed before generating numbers:
gRandom->SetSeed(12345);
For more realistic, non reproducible runs, use a varying seed, for example derived from the current time.
The simplest usage of TRandom is to obtain a uniform random number in the interval $(0,1)$ with the method Rndm():
double x = gRandom->Rndm(); // uniform in (0, 1)
If you want a uniform number in a different interval, for example between $a$ and $b$, you can rescale:
$$
x_{\text{scaled}} = a + (b - a)\,x
$$
where $x$ is uniform in $(0,1)$. In C++ with ROOT you can write:
double x = gRandom->Rndm();
double a = -5.0;
double b = 5.0;
double x_scaled = a + (b - a) * x; // uniform in (-5, 5)
TRandom also provides methods that directly sample from common distributions, which will be discussed conceptually in the later chapter on distributions. Here you only need to know that TRandom has convenience functions such as:
double g = gRandom->Gaus(mean, sigma); // Gaussian (normal) distribution
double e = gRandom->Exp(tau); // Exponential distribution
double p = gRandom->Poisson(mean); // Poisson distributed integerThese methods internally use the uniform generator and transform the values to the requested distribution.
You can control the seed of any TRandom instance with SetSeed() and check it with GetSeed():
gRandom->SetSeed(1234); // fixed seed, reproducible sequence
int seed = gRandom->GetSeed();
If you call SetSeed(0), ROOT will choose a seed based on the current time, which changes each run.
In many analysis scripts you can use gRandom everywhere. In more complex simulations that involve several independent random streams, for example different components of a detector, you may create separate generator objects:
TRandom myGen(9876); // constructor sets seed
double x = myGen.Rndm();This keeps the random sequences separate, which can make debugging and reproducibility easier, especially when you later switch to more advanced generators.
TRandom3
TRandom3 is a specific implementation of the TRandom interface that uses the Mersenne Twister algorithm. In practice TRandom3 is the recommended default generator in ROOT for most applications, because it has a very long period and good statistical properties compared with older generators.
You can use TRandom3 directly, or you can tell ROOT to make gRandom an instance of TRandom3. The usage pattern is almost identical to TRandom, but you construct TRandom3 explicitly:
#include "TRandom3.h"
TRandom3 r3(1234); // seed in constructor
double u = r3.Rndm(); // uniform (0, 1)
double g = r3.Gaus(0.0, 1.0);
If you prefer to keep using the global gRandom pointer, you can replace it with a TRandom3 instance:
gRandom = new TRandom3(1234); // make global generator a TRandom3
double x = gRandom->Rndm();
The methods available on TRandom3 are the same as on TRandom, because TRandom3 is a subclass. This means you use the same Rndm(), Gaus(), Exp(), and Poisson() calls. The main difference is the internal algorithm.
For any new ROOT-based simulation, prefer TRandom3 over the historical TRandom implementation. Use:
gRandom = new TRandom3(seed);
as one of the first lines in your macro to ensure a high-quality random sequence.
You can also seed TRandom3 after construction with SetSeed(). A seed of zero again selects a time based seed:
TRandom3 r3; // default constructor
r3.SetSeed(0); // time-based seed
double val = r3.Rndm();
In later sections on simulations and Monte Carlo methods you will repeatedly call these random methods inside loops, typically to generate synthetic events or to smear ideal quantities with detector resolution. At that stage, choosing TRandom3 and setting its seed consistently becomes an important part of making your simulation both reliable and reproducible.
Views: 10
KAHIBARO