Leepoint Java Reference Notes on the Java language and its standard library.

BigInteger

Integers with no size limit, at the cost of every operation being a method call.

long holds up to about 9.2 × 10¹⁸. Beyond that it silently wraps — no exception, just a wrong answer with the wrong sign. BigInteger has no limit but available memory.

BigInteger a = new BigInteger("123456789012345678901234567890");
BigInteger b = BigInteger.valueOf(42);
BigInteger sum = a.add(b);

No operators

The arithmetic operators do not work. Everything is a method:

a.add(b)          // a + b
a.subtract(b)     // a - b
a.multiply(b)     // a * b
a.divide(b)       // a / b, integer division
a.mod(b)          // a % b, always non-negative
a.pow(10)         // a to the tenth
a.negate()
a.abs()

BigInteger is immutable, so every one of these returns a new object and none modify the receiver. a.add(b); on its own line does nothing — a mistake that compiles cleanly.

Comparing

a.equals(b)          // equality
a.compareTo(b) < 0   // ordering
a.signum()           // -1, 0 or 1

Never ==. And a specific trap: equals requires the same value and type, so a BigInteger and a BigDecimal of equal value are not equal.

Constants

BigInteger.ZERO
BigInteger.ONE
BigInteger.TWO
BigInteger.TEN

Use valueOf for small values rather than the string constructor — it caches.

Factorial, the standard example

BigInteger factorial(int n) {
    BigInteger result = BigInteger.ONE;
    for (int i = 2; i <= n; i++) {
        result = result.multiply(BigInteger.valueOf(i));
    }
    return result;
}

21! already overflows long. This version does not.

Cost

Operations are O(number of digits) at best, worse for multiplication and division, and each allocates. Fine for cryptography, combinatorics or exact arithmetic; wasteful for values that comfortably fit in a long. Use it when you need it, not by default.

BigDecimal for money

Never use double for currency — 0.1 + 0.2 is not 0.3 in binary floating point, and the error accumulates.

BigDecimal price = new BigDecimal("19.99");

Construct from a string, not a double: new BigDecimal(0.1) captures the binary approximation and gives you a long tail of unexpected digits. And divide needs a rounding mode, or it throws when the result does not terminate.