Colby
Colby

Reputation: 454

Java convert two integers to a double from 1 to 0

I am working with an ISAAC implementation which generates random integers. I need to create a Gaussian value with these integers. First, I need to change them to a double from 0 to 1 though. How can I do this in Java? Here is what I have so far to convert the ints to doubles, but it still needs to be in the normal distribution. I am also using java.util.Random.nextGaussian() logic to convert the double to Gaussian.

public double nextDouble() {
    long l = ((long)(nextInt()) << 32) + nextInt();
    return Double.longBitsToDouble(l);
}

What is the fastest possible way (cpu cycle wise) to do this?

Upvotes: 0

Views: 547

Answers (2)

Severin Pappadeux
Severin Pappadeux

Reputation: 20080

Converting 64bit long to U(0,1) is not a simple task. I would recommend to read here.

As far as I can see, in Java world scalb is equivalent to ldexp, so code would be

public double nextDouble() {
    return Math.scalb((double)nextLong(), -64);
}

Upvotes: 2

Stefan Zobel
Stefan Zobel

Reputation: 3212

If you want to use ISAAC by all means, then use the 64bit version that gives you a nextLong() as a primitive. Generating a double is then simply

protected static final double DOUBLE_NORM = 1.0 / (1L << 53);

public double nextDouble() {
    return (nextLong() >>> 11) * DOUBLE_NORM;
}

From there you can go on using Marsaglia's polar method for the nextGaussian() method, the same way it is done in java.util.Random

Edit: I've tested 32bit & 64bit ISAAC a couple of years ago. Of course, I don't remember the exact numbers, but you might be surprised how much more throughput you can get with the 64bit version if you really need 64 random bits.

Edit 2: If you also need 32 random bits for integers you are of course wasting a lot of work with the 64bit algorithm (32bit is definitely faster here). In my work I need mostly doubles, so 64bit is the way to go (for me).

Edit 3: nextFloat() would be

protected static final float FLOAT_NORM = 1.0F / (1 << 24);

public float nextFloat() {
    return (nextLong() >>> 40) * FLOAT_NORM;
}

Upvotes: 3

Related Questions