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’m Anni Huang, an AI researcher-in-training currently at ByteDance, specializing in LLM training operations with a coding focus. I bridge the gap between engineering execution and model performance, ensuring the quality, reliability, and timely delivery of large-scale training projects.