Hi there,
from what I can see, uniform_real(min,max) essentially does this:
fp_type result = uniform_fp_between_0_and_1 * (max - min) + min; // (1)
(1) will fail e.g. if the distance between min and max is >
std::numeric_limits::max()
While writing unit tests for my code I have come across exactly this
situation. My application would not suffer much from reducing the allowed
value range for my variables to < +/-0.5*std::numeric_limits::max()
. However I feel that this would be a bit artificial.
Hence I was wondering whether code like the following made more sense
(although it is certainly not as efficient):
/**********************************************************/
fp_type uniform_real(const fp_type& min, const fp_type& max) {
// Check that min and max have appropriate values
assert(min<=max);
if(min >= fp_type(0.) || max <= fp_type(0.)) { // (max-min) is valid
return uniform_01() * (max - min) + min;
} else { // Some values will fail (max-min)
// We know: min<0., max>0.
assert(min<0);
assert(max>0);
// Calculate a random number in the range [0,1[
fp_type fraction = uniform_01();
// Calculate the fraction of the distance of min from 0.
volatile fp_type minFraction = -fraction*min;
// Calculate the fraction of the distance of max from 0.
volatile fp_type maxFraction = fraction*max; //
// The start of the scale
volatile fp_type result = min + minFraction;
// Add maxFraction to the result.
result += maxFraction;
return result;
}
}
/**********************************************************/
Essentially, in cases where (max-min) could be larger than the allowed value
range, the distance to 0 of each max and min is individually multiplied with
a fp random number in the range [0,1[ . The resulting values are then added
seperately to min. There should be no situation where an attempt is made to
create a value larger than the allowed value range ... unless the compiler
optimizes this to "result=min+minFraction+maxFraction;" or worse. volatile
might or might not prevent this, I am not sure (seems to work with g++
4.4.3, though).
What is your view on this ? Are there different/better approaches in Boost
that I could use ?
Best Regards,
Ruediger