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



Reply via email to