title: Increasing Java's BigInteger performance
body: <p>How to increase performance of Java's Big Integer?</p>
  
  <p>For example, this factorial program:</p>
  
  <pre><code>import java.math.*;
  class Fac {
    public static void main(String[] args) {
      BigInteger i = BigInteger.ONE;
      for(BigInteger z=BigInteger.valueOf(2);z.compareTo(BigInteger.valueOf(99999)) != 0;) {
        i = i.multiply(z);
        z = z.add(BigInteger.ONE);
      }
      System.out.println( i );
    }
  }
  </code></pre>
  
  <p>That program completed in <code>31.5</code>s</p>
  
  <p>Where's in C++:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;gmpxx.h&gt;
  using namespace std;
  int main() {
    mpz_class r;
    r = 1;
    for(int z=2;z&lt;99999;++z) {
      r *= mpz_class(z);
    }
    cout &lt;&lt; r &lt;&lt; endl;
  }
  </code></pre>
  
  <p>completed in <code>1.0</code>s</p>
  
  <p>And Ruby (for comparison):</p>
  
  <pre><code>puts (2...99999).inject(:*)
  </code></pre>
  
  <p>completed in <code>4.4</code>s (Ruby) and <code>32.2</code>s in JRuby</p>
  
  <p>And also Go (for comparison):</p>
  
  <pre><code>package main
  import (
   "fmt"
   "math/big"
  )
  func main() {
    i := big.NewInt(1);
    one := big.NewInt(1)
    for z := big.NewInt(2); z.Cmp(big.NewInt(99999)) &lt; 0;  {
        i.Mul(i,z);
        z.Add(z,one)
    }
    fmt.Println( i );
  }
  </code></pre>
  
  <p>completed in <code>1.6</code>s and <code>0.7</code>s for <code>MulRange</code></p>
  
  <p><strong>EDIT</strong> As requested:</p>
  
  <pre><code>import java.math.*;
  class F2 {
    public static void main(String[] args) {
      BigInteger i = BigInteger.ONE, r = BigInteger.valueOf(2);
      for(int z=2; z&lt;99999 ; ++z) {
        i = i.multiply(r);
        r = r.add(BigInteger.ONE);
      }
      System.out.println( i );
    }
  }
  </code></pre>
  
  <p>runtime duration: <code>31.4</code> s</p>
  
  <p><strong>EDIT 2</strong> for those who still think that the first and second java code is unfair.. </p>
  
  <pre><code>import java.math.*;
  class F3 {
    public static void main(String[] args) {
      BigInteger i = BigInteger.ONE;
      for(int z=2; z&lt;99999 ; ++z) {
        i = i.multiply(BigInteger.valueOf(z));
      }
      System.out.println( i );
    }
  }
  </code></pre>
  
  <p>completed in <code>31.1</code>s</p>
  
  <p><strong>EDIT 3</strong> @OldCurmudgeon comment:</p>
  
  <pre><code>import java.math.*;
  import java.lang.reflect.*;
  class F4 {
    public static void main(String[] args) {
      try {
        Constructor&lt;?&gt; Bignum = Class.forName("java.math.MutableBigInteger").getDeclaredConstructor(int.class);
        Bignum.setAccessible(true);
        Object i = Bignum.newInstance(1);
        Method m = i.getClass().getDeclaredMethod("mul", new Class[] { int.class, i.getClass()});
        m.setAccessible(true);
        for(int z=2; z&lt;99999 ; ++z) {
          m.invoke(i, z, i);
        }
        System.out.println( i );
      } catch(Exception e) { System.err.println(e); } 
    }
  }
  </code></pre>
  
  <p>completed in <code>23.7</code>s</p>
  
  <p><strong>EDIT 4</strong> As stated by @Marco13 the biggest problem was on the string creation not on the BigInteger itself..</p>
  
  <ul>
  <li>BigInteger: <code>3.0</code>s</li>
  <li>MutableBigInteger hack: <code>10.1</code>s</li>
  <li>String creation: ~<code>20</code>s</li>
  </ul>