Doc. no.: N3796
Date: 2013-10-02
Project: Programming Language C++, Library Evolution Working Group
Reply-to: Zhihao Yuan <zy at miator dot net>

std::rand replacement

Motivation

We want to deprecate std::rand friends, while “deprecation without a replacement” is a valid concern. This paper

  1. Propose replacement to the std::rand friends. As a global uniform random number generator, std::rand is considered both handy and useful.

  2. Expose the most widely-used combos from C++11 <random> without pushing the users to learn the whole design of <random>. Smoothing the learning curve can usually optimize the acceptance.

Design Decisions

std::rand is a single interface, and its “replacement” should be able to be used as a single interface as well. In addition, I expect the interface to correctly expose the functionalities of <random> and lead to more robust and secure programs. The proposed replacement is

Seeding a pseudo random number generator with a determined value will result in a determined random number sequence (repeatability), which is useful for debugging. However, a global seeding utility is incompatible with the proposed minimal interface, and causes numerous confusions in a multi-thread environment. Instead, an implementation may want to allow user to deploy a determined seed for debugging purpose.

Different from the initial draft of this paper, only the utility using uniform_int_distribution is proposed; the one using uniform_real_distribution is dropped. This is because the former forms a “selection” model, which covers the major use cases, while the later is merely a simulation of data input.

Example

std::randint(0, 6);  // randomly seeded

Wording

Change 26.5.2 rand.synopsis:

namespace std {

 // 26.5.7.2, function template generate_canonical
 template<class RealType, size_t bits, class URNG>
 RealType generate_canonical(URNG& g);
// 26.5.7.3, function template randint
template<class IntType>
  IntType randint(IntType a, IntType b);
 // 26.5.8.2.1, class template uniform_int_distribution
 template<class IntType = int>
 class uniform_int_distribution;

} // namespace std

New section 26.5.7.3 rand.util.randint:

26.5.7.3 function template randint

All functions instantiated from the template described in this section 26.5.7.3 share the same default_random_engine for a given execution of a thread; the random engine is non-deterministically seeded during the initialization. Such a random engine shall be maintained separately for each thread. [Note: The call expressions from different threads shall not be able to observe the same pseudo random number sequence in a deterministic way. –end note]

template<class IntType>
  IntType randint(IntType a, IntType b);

Requires: a b

Effects: Produce a random integer i, a ≤ i ≤ b, from a uniform_int_distribution<IntType> (26.5.8.2.1).

Returns: i.

Sample Implementation

A sample implementation is available at https://github.com/lichray/randint …You really need this?

Bikeshed

First of all, overloading std::rand is not an option. User may regard std::rand() as a “safe” variant to the new interface.

Collected so far:

Acknowledgments

Hans Boehm, who emphasized the importance of an enforced per-thread random engine more than once.

Stephan T. Lavavej, who carefully reviewed this paper and provided many corrections.

Walter E. Brown, who drafted the paper[1] which contains basically the same thought.

And many others who joined the std::rand related discussions on c++std-lib and c++std-lib-ext mailing lists.

References

[1] Brown, Walter E. N3742 Three <random>-related Proposals, v2. http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3742.pdf

[2] random – Generate pseudo-random numbers. “The Python Standard Library”. http://docs.python.org/2/library/random.html