Java Int Overflow - How to avoid it?

Anni HuangAnni Huang
3 min read

Integer overflow is a common source of bugs in programming. Here are the key scenarios when you should be particularly vigilant:

High-Risk Scenarios

1. Mathematical Operations with Large Numbers

// Dangerous - can overflow
int result = a * b;
long factorial = 1;
for (int i = 1; i <= n; i++) {
    factorial *= i; // factorial grows very quickly
}

// Safe alternatives
long result = (long) a * b;
BigInteger factorial = BigInteger.ONE;
for (int i = 1; i <= n; i++) {
    factorial = factorial.multiply(BigInteger.valueOf(i));
}

2. Combinatorics Calculations

// C(n,k) = n! / (k! * (n-k)!) or n*(n-1)*...*(n-k+1) / k!
// Both can overflow quickly

// Dangerous
int combinations = n * (n-1) / 2; // Your case!

// Safe
long combinations = (long) n * (n-1) / 2;

3. Array Size Calculations

// When dealing with large arrays
int n = array.length;
int totalPairs = n * (n-1) / 2; // Overflow risk when n > ~65,000

// Better
long totalPairs = (long) n * (n-1) / 2;

4. Cumulative Operations

// Sum of large arrays
int sum = 0;
for (int val : largeArray) {
    sum += val; // Can overflow
}

// Safer
long sum = 0;
for (int val : largeArray) {
    sum += val;
}

Quick Mental Math Rules

When int Overflows (2³¹ - 1 = 2,147,483,647):

  • Two 5-digit numbers: 50,000 × 50,000 = 2.5B ✅ (close to limit)
  • Two 6-digit numbers: 100,000 × 100,000 = 10B ❌ (overflow)
  • Factorials: 13! = 6.2B ❌, but 12! = 479M
  • Squares: √(2¹³¹) ≈ 46,340, so n² overflows when n > ~46,000

Common Overflow Thresholds:

// These are near the danger zone:
int maxSafeSquare = 46340;      // 46340² still fits in int
int maxSafeSum = 2147483647;    // Obviously
int maxSafePairCount = 65535;   // n*(n-1)/2 for n=65536 overflows

Best Practices

1. Default to long for Intermediate Calculations

// Even if inputs are int, use long for calculations
public int calculateSomething(int a, int b) {
    long result = (long) a * b + (long) a * a;
    return (int) result; // Cast back if needed
}

2. Check Input Constraints

// If problem says: 1 ≤ n ≤ 10⁵
// Then n*(n-1)/2 could be up to ~5×10⁹ → use long

// If problem says: 1 ≤ n ≤ 10³  
// Then n*(n-1)/2 is at most ~5×10⁵ → int is fine

3. Use Libraries for Very Large Numbers

import java.math.BigInteger;

// For extremely large calculations
BigInteger huge = new BigInteger("999999999999999999");
BigInteger result = huge.multiply(huge);

4. Overflow Detection (if needed)

public static boolean willOverflow(int a, int b) {
    if (a == 0 || b == 0) return false;
    return a > Integer.MAX_VALUE / b;
}

// Or use Math.multiplyExact() which throws on overflow
try {
    int result = Math.multiplyExact(a, b);
} catch (ArithmeticException e) {
    // Handle overflow
}

Red Flags in Code

Watch out when you see:

  • n * (n-1) or n * n with large n
  • Factorial calculations
  • Powers: a^b where b > 10
  • Cumulative sums over large datasets
  • Time complexity calculations (like your pairs problem)
  • Converting from larger types: (int) someDoubleValue

Language-Specific Notes

  • Java: int is 32-bit signed, long is 64-bit signed
  • C++: int size varies, use long long for safety
  • Python: Integers have arbitrary precision (no overflow!)
  • JavaScript: Uses 64-bit floats, but bitwise ops use 32-bit

The key is developing intuition: if you're multiplying numbers that could be in the tens of thousands or larger, strongly consider using long.

0
Subscribe to my newsletter

Read articles from Anni Huang directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Anni Huang
Anni Huang

I am Anni HUANG, a software engineer with 3 years of experience in IDE development and Chatbot.