FULL PRODUCT VERSION :
java version "1.6.0_21"
Java(TM) SE Runtime Environment (build 1.6.0_21-b06)
Java HotSpot(TM) Server VM (build 17.0-b16, mixed mode)
A DESCRIPTION OF THE PROBLEM :
The method "multiply" in class java.math.BigInteger is twice as slow as it needs to be when called on a large number with a smaller number as a parameter.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run supplied code
2. Observe different performance characteristics for the two different methods
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Performance characteristics should be the same in both cases.
ACTUAL -
One method is twice as slow as the other.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.math.BigInteger;
public class Factorial
{
public static BigInteger fact1 (BigInteger n)
{
BigInteger n0 = n;
BigInteger f = BigInteger.ONE;
while (n0.compareTo (BigInteger.ZERO) > 0)
{
f = n0.multiply (f);
n0 = n0.subtract (BigInteger.ONE);
}
return f;
}
public static BigInteger fact2 (BigInteger n)
{
BigInteger n0 = n;
BigInteger f = BigInteger.ONE;
while (n0.compareTo (BigInteger.ZERO) > 0)
{
f = f.multiply (n0);
n0 = n0.subtract (BigInteger.ONE);
}
return f;
}
public static void main (String[] args)
{
BigInteger n = BigInteger.valueOf (5000);
System.out.println ("Doing factorial for " + n);
long t0 = System.currentTimeMillis ();
fact1 (n);
long t1 = System.currentTimeMillis ();
fact2 (n);
long t2 = System.currentTimeMillis ();
System.out.println ("Method 1 took " + (t1 - t0) + "ms");
System.out.println ("Method 2 took " + (t2 - t1) + "ms");
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Where performance is critical, add a check on the magnitude of the numbers before multiplying.