This question: How to create a random BigInteger describes a way to achieve the same semantics as Random.nextInt (int n) for BigIntegers.
I would like to do the same for BigDecimal and Random.nextDouble ().
One answer in the above question involves creating a random BigInteger and then creating a BigDouble from it with a random scale. A very quick experiment shows that this is a very bad idea :)
My intuition is that using this method requires an integer to scale something like n-log10(R), where n is the number of precision digits needed for output, and R is a random BigInteger. This should allow the correct number of digits to be present so that (for example) 1 → 10 ^ -64 and 10 ^ 64 → 1.
The scaling value must also be correctly selected so that the result falls into the range [0,1].
Has anyone done this before and they know if the results are distributed correctly? Is there a better way to achieve this?
EDIT: Thanks to @biziclop for correcting my understanding of the scale argument. The foregoing is not required; a constant scale factor has the desired effect.
For later reference, my (apparently working code):
private static BigDecimal newRandomBigDecimal(Random r, int precision) {
BigInteger n = BigInteger.TEN.pow(precision);
return new BigDecimal(newRandomBigInteger(n, r), precision);
}
private static BigInteger newRandomBigInteger(BigInteger n, Random rnd) {
BigInteger r;
do {
r = new BigInteger(n.bitLength(), rnd);
} while (r.compareTo(n) >= 0);
return r;
}