
Boost : 
From: Doug Gregor (dgregor_at_[hidden])
Date: 20041230 17:24:34
I'm having a few problems dealing with uniform_real and uniform_01.
The basic issue is that uniform_real does not always produce values
between its min and its max. The problem consistently occurs when I'm
using minstd_rand as my generator (one of the linear_congruential
variants). For instance, if I write:
template<typename RandomNumberGenerator>
void foo(RandomNumberGenerator& gen)
{
uniform_int<int> rand_int(some_min_int, some_max_int);
// Okay, some_min_int <= x <= some_max_int
int x = rand_int(gen);
uniform_real<double> rand_double(some_min_double, some_max_double);
// Uhoh, some_min_double <= y <= some_max_double doesn't always
hold
double y = rand_double(gen);
}
Looking at the source to uniform_real, the problem is obvious:
result_type operator()(Engine& eng) { return eng() * (_max  _min) +
_min; }
uniform_real assumes that the engine returns a value in [0, 1], but
doesn't check that. If this is correct (I hope it isn't!), the
"obvious" answer is to use uniform_01<RandomNumberGenerator...> as
input to uniform_real. However, uniform_01 is also broken in several
ways:
1) It isn't a random distribution because its operator() does not
accept an engine. Instead, the engine is embedded in the uniform_01
object.
2) uniform_01 stores the incoming random number generator by _value_,
so the original generator "gen" does not advance. You can't even fake
it with uniform_01<RandomNumberGenerator&>, because that creates
referencetoreference problems.
Below is a small patch to make uniform_real<...> behave nicely. As for
uniform_01: we should deprecate it in 1.33.0 and remove it afterwords,
because it is hopelessly broken and not even included in the TR.
Doug
Index: uniform_real.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/random/uniform_real.hpp,v
retrieving revision 1.14
diff u r1.14 uniform_real.hpp
 uniform_real.hpp 27 Jul 2004 03:43:32 0000 1.14
+++ uniform_real.hpp 30 Dec 2004 22:11:33 0000
@@ 50,7 +50,11 @@
void reset() { }
template<class Engine>
 result_type operator()(Engine& eng) { return eng() * (_max  _min) +
_min; }
+ result_type operator()(Engine& eng) {
+ return static_cast<result_type>(eng()  eng.min())
+ / (eng.max()  eng.min())
+ * (_max  _min) + _min;
+ }
#if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) &&
!defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<class CharT, class Traits>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk