The UniformRandomProvider and ContinuousUniformSampler can create
doubles uniformly in a range [0, 1) and [x, y).
I would like to create a sampler that can create doubles with random
mantissa bits and a specified range of exponents. These would not follow
a standard distribution but would be distributed according to the IEEE
754 floating-point "double format" bit layout.
The sampler would ensure all bits of the mantissa are uniformly sampled
and the exponent range is uniformly sampled. It could be used for
example to create random double data in a specified range for testing.
Following from UniformRandomProvider I propose to remove the sign bit to
allow a maximum range sampler from [0, Double.MAX_VALUE]. Thus we have
the API:
public final class FiniteDoubleSampler {
/**
* Creates a new finite double sampler.
*
* <p>This will return double values from the entire exponent range of
a finite
* {@code double} including sub-normal numbers. The value will be unsigned.
*
* @param rng Generator of uniformly distributed random numbers.
* @return Sampler.
* @since 1.4
*/
public static SharedStateContinuousSampler of(UniformRandomProvider rng);
/**
* Creates a new finite double sampler.
*
* <p>This will return double values from the specified exponent range
of a finite
* {@code double}. This assumes all sub-normal numbers are identified
with the exponent -1023.
* The value will be unsigned.
*
* @param rng Generator of uniformly distributed random numbers.
* @param minExponent Minimum exponent
* @param maxExponent Maximum exponent
* @see Double#MIN_EXPONENT
* @see Double#MAX_EXPONENT
* @throws IllegalArgumentException If the exponents are not in the
range -1023 inclusive
* to 1023 inclusive; or the min exponent is not {@code <=} max exponent.
* @return Sampler.
* @since 1.4
*/
public static SharedStateContinuousSampler of(UniformRandomProvider rng,
int minExponent,
int maxExponent);
}
I have written many tests where I wanted full precision random mantissas
in double values and wanted the doubles to represent all doubles that
could occur. Thus randomly sampling from the IEEE 754 representation
seems to be more generic than for example rng.nextDouble() * constant.
For example:
// Random numbers: [0, Double.MAX_VALUE]
FiniteDoubleSampler.of(rng);
FiniteDoubleSampler.of(rng, -1023, 1023);
// Random sub-normal numbers: [0, Double.MIN_NORMAL)
FiniteDoubleSampler.of(rng, -1023, -1023);
// Random numbers that are close to overflow: (Double.MAX_VALUE/2,
Double.MAX_VALUE]
FiniteDoubleSampler.of(rng, 1023, 1023);
// Random numbers in the range [1, 32)
FiniteDoubleSampler.of(rng, 0, 4);
Thoughts on this?
Alex