[random] infinite loop in uniform_real_distribution
Hello,
I'm using Boost 1.54.
The following code hangs in infinite loop when generating a single
floating point number :
#include
On Mon, Nov 25, 2013 at 11:16 AM, Jérémy Coulon
Hello,
I'm using Boost 1.54. The following code hangs in infinite loop when generating a single floating point number :
#include
#include <iostream> #include <limits> int main() { boost::random::mt19937 rng; boost::random::uniform_real_distribution<float> distrib( -std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
std::cout << distrib(rng) << std::endl; return 0; }
I can reproduce the bug with both - Linux GCC 4.8 x86_64 and - Windows VisualStudio 2012 32bits
It looks like this uniform distribution doesn't work if the range [min,max] is large. From uniform_real_distribution.hpp:61 T result = numerator / divisor * (max_value - min_value) + min_value;
Here the operation (max_value - min_value) produces an overflow.
Regards, Jeremy
It seems to me that it's not really just "large" that is the issue, but only if you have a range larger than std::numeric_limits<float>::max(). Ideally, you'd not really want to be messing with too very many numbers that are within many orders of magnitude of the max float value, as your precision will be awful. Are you just edge-case testing, or do you have a real reason to generate uniform distributions over this range? Brian
It seems to me that it's not really just "large" that is the issue, but only if you have a range larger than std::numeric_limits<float>::max(). Ideally, you'd not really want to be messing with too very many numbers that are within many orders of magnitude of the max float value, as your precision will be awful. Are you just edge-case testing, or do you have a real reason to generate uniform distributions over this range?
Brian The documentation doesn't say anything about the input range of the distribution. So I expect it to work with *any* range. As for the real reason, I need to unit-test a function of my own code
Le 25/11/2013 22:03, Brian Budge a écrit : that takes a float as an argument. I want to test that my function behaves correctly for any given float. Using a few thousands of randomly generated floats and calling my function with that seems a good idea. Jeremy
On Mon, Nov 25, 2013 at 1:27 PM, Jérémy Coulon
Le 25/11/2013 22:03, Brian Budge a écrit :
It seems to me that it's not really just "large" that is the issue, but only if you have a range larger than std::numeric_limits<float>::max(). Ideally, you'd not really want to be messing with too very many numbers that are within many orders of magnitude of the max float value, as your precision will be awful. Are you just edge-case testing, or do you have a real reason to generate uniform distributions over this range?
Brian
The documentation doesn't say anything about the input range of the distribution. So I expect it to work with *any* range.
Fair enough :) I'd say that you are right that it should be documented.
As for the real reason, I need to unit-test a function of my own code that takes a float as an argument. I want to test that my function behaves correctly for any given float. Using a few thousands of randomly generated floats and calling my function with that seems a good idea.
Sure. I suppose you have other test cases for inf, NaN, and denorm values? How will you know it behaves correctly for the random input (unless of course, you have another implementation that can run in lockstep to verify correctness?). Sorry, I'm sure you're not here looking for criticism of your testing methods :) You can achieve what you want by generating a random number on [-1, 1] and multiplying it by the max float. I don't think that there is a *general* way to arrive at a uniform distribution of a range greater than max float by first generating a random number on [0, 1), so it's unlikely that the library can be "fixed" to achieve what you want. Another method would be to use double precision generation on the max float range, and then convert to float.
Jeremy
Brian
AMDG On 11/25/2013 02:22 PM, Brian Budge wrote:
You can achieve what you want by generating a random number on [-1, 1] and multiplying it by the max float. I don't think that there is a *general* way to arrive at a uniform distribution of a range greater than max float by first generating a random number on [0, 1), so it's unlikely that the library can be "fixed" to achieve what you want.
It's really quite easy. if ( max - min == infinity ) { divisor = 2; min /= divisor; max /= divisor; } else { divisor = 1; } // compute a value in [min, max) as usual result *= divisor;
Another method would be to use double precision generation on the max float range, and then convert to float.
In Christ, Steven Watanabe
On Mon, Nov 25, 2013 at 2:53 PM, Steven Watanabe
AMDG
On 11/25/2013 02:22 PM, Brian Budge wrote:
You can achieve what you want by generating a random number on [-1, 1] and multiplying it by the max float. I don't think that there is a *general* way to arrive at a uniform distribution of a range greater than max float by first generating a random number on [0, 1), so it's unlikely that the library can be "fixed" to achieve what you want.
It's really quite easy.
if ( max - min == infinity ) { divisor = 2; min /= divisor; max /= divisor; } else { divisor = 1; }
Ah, I see. Nice :) Thanks for suggesting another simple solution. Brian
On Mon, Nov 25, 2013 at 2:53 PM, Steven Watanabe
wrote: It's really quite easy.
if ( max - min == infinity ) { divisor = 2; min /= divisor; max /= divisor; } else { divisor = 1; }
Thank you Steven for your solution. I just searched on Boost Trac and found this 8 months old ticket: https://svn.boost.org/trac/boost/ticket/8351
It looks like the same bug we are talking about even if it is not really related to #6059. Is there any chance to see it fixed in the next Boost release ? Thank you both for your time. Regards, Jeremy
On Mon, Nov 25, 2013 at 2:53 PM, Steven Watanabe
AMDG
On 11/25/2013 02:22 PM, Brian Budge wrote:
You can achieve what you want by generating a random number on [-1, 1] and multiplying it by the max float. I don't think that there is a *general* way to arrive at a uniform distribution of a range greater than max float by first generating a random number on [0, 1), so it's unlikely that the library can be "fixed" to achieve what you want.
It's really quite easy.
if ( max - min == infinity ) { divisor = 2; min /= divisor; max /= divisor; } else { divisor = 1; }
Ah, I see. Nice :) Thanks for suggesting another simple solution. Brian
participants (3)
-
Brian Budge
-
Jérémy Coulon
-
Steven Watanabe