You are here:

- Home
- Computing/Technology
- C/C++
- C++
- random long long in C/C++

Advertisement

Hello,

I am trying to generate a uniformly distributed pseudo-random number of 12 digits. The problem is rand() and random() both only return int/long type (10 digits max).

Is there any function which generate pseudo-random number in long long int type?

Thank you

If you are asking is there an ISO standard C++ library function to produce such a value then, assuming we are talking about the current 1998 or 2003 bug-fix update of the ISO C++ standard the answer is no. (Note that long long integer types are also not part of the current C++ standard).

In fact although the returned value from rand() is an int (not a long - they are _not_ equivalent on all implementations), the standard only requires values in the range 0 ... 32767, that is RAND_MAX is only required to have a value of at least 32767. Thus even on popular 32-bit compilers where an int can hold values as large as 2147483647 it may be that the range of random numbers produced by rand is restricted to 0 to 32767.

So what can you do?

Well my first thought is that you could build a single value from multiple random numbers:

const int RandMaxBitLength(15); // assumes RAND_MAX is 32767

long long r( rand() );

r <<= RandMaxBitLength;

r += rand();

r <<= RandMaxBitLength;

r += rand();

Where 15 is the number of bits used by 32767. If RAND_MAX were 2147483647 say then the value for RandMaxBitLength would be 31 and only 2 calls to rand would be required. If this approach seems feasible to you I shall leave it to you to tidy things up. The reason I am not sure if such an approach would be acceptable is that I have no idea what the resultant distribution of such composite random values would be compared to that produced by rand - which in fact has no guarantees on uniformity - the C 1999 standard just says the following for rand:

"The rand function computes a sequence of pseudo-random

integers in the range 0 to RAND_MAX."

So if you are serious about pseudo random number generation you should be looking outside the standard C/C++ library. I do not have any such 3rd party libraries to hand but I would start by using an Internet search using Google, Yahoo, Msn or similar. One place I know caters for maths and science development needs is the MathTools web site at http://www.mathtools.net/. The C and C++ random number section is at http://www.mathtools.net/C_C__/Random_numbers/index.html.

However the TR1 non-normative library update to the ISO C++ standard includes a new random number generation framework. [note: non-normative means that a C++ implementation does not have to include these features to be standard compliant; however such features will most likely be incorporated into the next full release of the ISO C++ standard].

This is a lot more sophisticated than the simple srand/rand/RAND_MAX facilities inherited from C. It defines a set of pseudo random number generator (PRNG) engine class templates, a set of random distribution class templates and a variate generator class template that uses a specific engine type with a specific distribution type. It also defines a random device type that produces non-deterministic random numbers.

As the TR1 update it is quite new and not widely supported by C++ implementations yet and I have not required industrial strength pseudo random number generation I have not made use of these facilities. I shall try below to give you an overview however. Sorry if it is not as clear or accurate as it could be...I will be working it out as I go along from the TR1 draft document at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf (the random number stuff is in section 5.1).

Note that although TR1 is not yet widely provided with C++ implementations (Microsoft are one of the first and have just released a version for Visual C++ 2008), there is an implementation in the Boost libraries (http://www.boost.org/) specifically see http://www.boost.org/doc/libs/1_35_0/libs/random/index.html. You should also read the usage information for the Boost TR1 implementation at http://www.boost.org/doc/libs/1_35_0/doc/html/boost_tr1/usage.html. Boost is where many of the TR1 features originated by the way, and is free for download and use. Note that many Linux distributions come with pre-build packages for the Boost libraries so see if it is either installed or available as a package if you are using Linux.

In what follows I shall leave off namespace qualifications for clarity. The class template definitions etc. are in fact in the std::tr1 namespace.

Ok let us start with PRNG engines. For example the linear_congruential class template is defined like so:

template <class UIntType, UIntType a, UIntType c, UIntType m>

class linear_congruential

{

public:

// types

typedef UIntType result_type;

// parameter values

static const UIntType multiplier = a;

static const UIntType increment = c;

static const UIntType modulus = m;

// constructors and member function

explicit linear_congruential(unsigned long x0 = 1);

template<class Gen> linear_congruential(Gen& g);

void seed(unsigned long x0 = 1);

template<class Gen> void seed(Gen& g);

result_type min() const;

result_type max() const;

result_type operator()();

};

In particular notice the UintType template type parameter and the m template parameter of the specified unsigned integer type. Part of the description of this engine reads:

"The template parameter UIntType shall denote an unsigned

integral type large enough to store values up to (m-1)."

This is because the m value is, as can be seen from the class template definition, used as a modulus for the generated values. In fact the transform function for the generator is given as:

"x(i+1) := (a * x(i) + c) mod m"

Note that the a and c template parameters should in general be less than the m template parameter.

The constructor is used to seed objects of these generator types and the call operator ( operator() ) is used to produce pseudo random number values.

There are some predefined types using these generator engine templates, which are useful to show the sort of values involved. Those using the linear_congruential class template are as follows:

typedef linear_congruential<implementation-defined , 16807, 0, 2147483647> minstd_rand0;

typedef linear_congruential<implementation-defined , 48271, 0, 2147483647> minstd_rand;

Where implementation-defined would presumably be some integer type capable of holding 2147483647 - i.e. a 32 bit type. However given this you could quite easily come up with a set of parameters based on an unsigned long long or other 64-bit type (on some implementations long or int could be 64-bits in size - those targeting 64-bit operating systems for example):

typedef linear_congruential<unsigned long long, 16807, 0, 999999999999ULL> rand12digits;

Whether the values of a and c need to be adjusted I cannot say - sorry I am a C++ expert not a pseudo random number expert.

I am unclear if all the provided PRNG engine class templates constitute uniform PRNGs. It is sort of implied but not clearly stated.

However once you have a generator of random numbers there are distribution class templates that can be used to provide a shaping of the distribution of values. One of these is the uniform_int distribution class template, which is parameterised on the type of int required.

template<class IntType = int>

class uniform_int

{

public:

// types

typedef IntType input_type;

typedef IntType result_type;

// constructors and member function

explicit uniform_int(IntType min = 0, IntType max = 9);

result_type min() const;

result_type max() const;

void reset();

template<class UniformRandomNumberGenerator>

result_type operator()(UniformRandomNumberGenerator& urng);

template<class UniformRandomNumberGenerator>

result_type operator()(UniformRandomNumberGenerator& urng, result_type n);

};

Thus we could define a uniform distribution type for use with unsigned long long values like so:

typedef uniform_int<unsigned long long> uniform_ulonglong;

You will notice we construct such a distribution from min, max values. The call operator uses an existing uniform PRNG to shape its results.

I presume the use of this distribution type is to modify the range of values from those output from a raw PRNG engine. So if you did not want 0 .... 999999999 but 1234 ... 123456789012 you could use a rand12digits with a suitably constructed uniform_ulonglong instance.

We can combine an engine with a distribution using the variate_generator class template. This takes as template parameters an underlying PRNG type and a distribution type:

template<class Engine, class Distribution>

class variate_generator

{

public:

typedef Engine engine_type;

typedef see below engine_value_type;

typedef Distribution distribution_type;

typedef typename Distribution::result_type result_type;

variate_generator(engine_type eng, distribution_type d);

result_type operator()();

template<class T> result_type operator()(T value);

engine_value_type& engine();

const engine_value_type& engine() const;

distribution_type& distribution();

const distribution_type& distribution() const;

result_type min() const;

result_type max() const;

};

This looks quite like the linear_congruential class template in what is provided - and that is the point. Given a generator engine type and a distribution type it combines then to produce a new generator engine. So I presume we can then use the rand12digits type as the engine and a uniform_int distribution with long long or unsigned long long as the integer type as the distribution type:

typedef variate_generator<rand12digits, uniform_ulonglong> uniform_rand12digits;

As far as I can tell we can create a uniform_rand12digits object from a rand12digits object and a uniform_ulonglong object:

rand12digits engine; // initialised using default value of 1 as seed

uniform_ulonglong distribution(1234, 123456789012ULL); // initialised with min, max values

uniform_rand12digits prng( engine, distribution);

unsigned long long value( prng() ); // get pseudo random number from our generator.

As you will note the new random number facilities are a lot more sophisticated than those inherited from C. One point that has to be made is that the state for these generators etc. is kept in the objects and is not static and global as it is for the C rand/srand functions. Hence you can have many different pseudo random number sequences active as you require, not just the single sequence provided by rand/srand.

As I happen to have Boost installed I tried the above suggested code (in fact I added a loop and some output) with Visual C++ 2005:

The full result was as follows:

#include <boost/tr1/random.hpp> // For Boost tr1 implementation of <random>

#include <iostream> // For std::cout

using namespace std::tr1; // As I left off namespace qualifications

typedef linear_congruential<unsigned long long, 16807, 0, 999999999999ULL> rand12digits;

typedef uniform_int<unsigned long long> uniform_ulonglong;

typedef variate_generator<rand12digits, uniform_ulonglong> uniform_rand12digits;

int main()

{

rand12digits engine; // initialised using default value of 1 as seed

uniform_ulonglong distribution(1234, 123456789012ULL); // initialised with min, max values

uniform_rand12digits prng( engine, distribution);

for ( int i=0; i <100; ++i)

{

unsigned long long value( prng() ); // get pseudo random number from our generator.

std::cout << std::setw(12) << value << ( !(i%6) ? '\n' : ' ');

}

std::cout << std::endl;

}

The output was as follows:

18040

282476482 6820784506 19384117468 48022031764 56687428522 4613307439

103620441178 54828202708 65365228105 99462084154 103553903998 121683597733

74438582506 89235457795 39577713592 71264115304 118444840537 85051441891

89035168801 105379946275 9546429121 88473630379 50083334521 9684237286

22057007962 94670547481 78369889690 113056786549 95811101110 62351343496

12807691501 11779150636 107966503198 37167167119 112962100471 60017135551

90613741207 80772621790 113137934950 77113825144 2537571436 93111041413

114743785111 4712075296 10604194102 39444966643 25568337040 47731760449

104141552803 60143664415 93727570678 106223169109 119667194371 11710781524

20339415025 41940276007 87531996079 38968679884 20380364224 38776030666

91363938655 59711493676 77147535856 62940659137 41050067107 2334225985

58278912322 61284101131 1866987949 8075373739 43655169778 94976189356

79490397274 7431961423 44442181174 13674154876 80523138394 43606090918

85040814814 46149566443 79911124795 4485912838 24345983206 9961330804

61726216567 126546904 3396305953 19925634058 25913376889 93730078156

74489272111 76899329812 76408652146 76739109529 75141398227 98793148177

45892717834 10206543181 47444565559

Obviously you will probably wish to improve on this example - e.g. randomise the seeding of engine, adjust the engine a and c values.

I hope that although this has not been an exhaustive tour of the subject that you will be able to get what you require. I was nicely surprised that the example code I produced while writing this answer actually worked as expected.

Have fun...

- Add to this Answer
- Ask a Question

Rating(1-10) | Knowledgeability = 10 | Clarity of Response = 8 | Politeness = 10 |

Comment | Thanks for the answer. Some of the part was a bit unclear to me so it took me a while before I finally got it, but mostly because I am just a C self learner with no extensive background in this language. Thank you again for the detailed answer. |

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines.
Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is).
When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD.
My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes.
I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.**Education/Credentials**