How to handle large numbers in Java

Key takeaways

  • Java's primitive data types have fixed sizes and ranges, making them unsuitable for large numbers, as they can lead to overflow.

  • Adding values that exceed the maximum limits of int and long can result in incorrect, negative values due to overflow, highlighting the need for more flexible solutions.

  • The BigInteger class allows the processing of arbitrarily large integers without overflow and supports a variety of arithmetic operations methods that will enable precise calculations on large numbers.

When programming in Java, we encounter scenarios where we must handle large numbers, such as calculating financial transactions with high precision or performing complex scientific computations. Java provides a mechanism to handle these efficiently.

This Answer will walk you through the basics of handling large numbers.

Let's start by discussing primitive data types that hold numerical values. We'll look at their sizes and limits, and then see how Java deals with big integers. This will help you understand how to calculate big numbers precisely and efficiently.

Primitive data types

Primitive data types are the data types available within a language. They are predefined by the language and named by a keyword. Common primitive types in Java include int, long, float, double, char, byte, short, and boolean.

Data types

Size (bits)

Range

byte

8

-128 to 127

short

16

-32,768 to 32,767

int

32

-231 to 231-1

long

64

-263 to 263-1

float

32

1.4e-045 to 3.4e+308

double

64

4.9e-324 to 1.8e+308

char

16

0 to 65,535

boolean

1

true or false

Limitations of primitive data types

While these types come with certain limitations that programmers need to be aware of:

Fixed-size and range

Each primitive data type has a fixed size, determining the range of values it can represent.

For example, an int in Java is a 32bit32-bit signed integer, which means it can represent values from 2,147,483,648-2,147,483,648 to 2,147,483,6472,147,483,647. Similarly, a long is a 64bit64-bit signed integer with a much larger range. However, once we exceed these limits, we encounter overflow.

Lack of flexibility

Primitive data types are not flexible in terms of size.

We cannot adjust their size to fit the needs of the application. For instance, if we need a number larger than a long can hold, we would need to use a different approach, such as using the BigInteger class in Java.

Example code demonstrating overflow

Here is an example that illustrates the concept of overflow with int and long data types in Java:

public class main {
public static void main(String[] args) {
// Example of int overflow
int largeInt = Integer.MAX_VALUE; // Maximum value an int can hold
System.out.println("Integer.MAX_VALUE: " + largeInt);
// This will overflow
largeInt = largeInt + 1;
System.out.println("After overflow, int: " + largeInt); // Incorrect value due to overflow
// Example of long overflow
long largeLong = Long.MAX_VALUE; // Maximum value a long can hold
System.out.println("Long.MAX_VALUE: " + largeLong);
// This will overflow
largeLong = largeLong + 1;
System.out.println("After overflow, long: " + largeLong); // Incorrect value due to overflow
}
}

Code explanation

  • Line 4: We define an int variable largeInt and assign it the maximum value an int can hold using Integer.MAX_VALUE.

  • Line 8: We then add 11 to largeInt, which causes an overflow, resulting in an incorrect, negative value.

  • Line 12: We define a long variable largeLong and assign it the maximum value of a long can hold using Long.MAX_VALUE.

  • Line 16: Adding 11 to largeLong also causes an overflow, resulting in an incorrect, negative value.

Using BigInteger to handle large numbers

BigInteger does not have a fixed size. It can grow to accommodate any integer value as long as there is enough memory available. It handles big values by using arrays of integers to represent the number.

Let's use the BigInteger and handle these large numbers:

import java.math.BigInteger;
public class main {
public static void main(String[] args) {
// Example of handling large numbers with BigInteger
BigInteger largeNumber = new BigInteger("9223372036854775808"); // Larger than Long.MAX_VALUE
System.out.println("BigInteger large number: " + largeNumber);
// Performing arithmetic operations without overflow
BigInteger anotherLargeNumber = new BigInteger("123456789012345678901234567890");
BigInteger sum = largeNumber.add(anotherLargeNumber);
BigInteger difference = largeNumber.subtract(anotherLargeNumber);
BigInteger product = largeNumber.multiply(anotherLargeNumber);
BigInteger quotient = largeNumber.divide(anotherLargeNumber);
BigInteger remainder = largeNumber.remainder(anotherLargeNumber);
System.out.println("Sum: " + sum);
System.out.println("Difference: " + difference);
System.out.println("Product: " + product);
System.out.println("Quotient: " + quotient);
System.out.println("Remainder: " + remainder);
}
}

Code explanation

  • Line 6: We create a BigInteger variable largeNumber initialized with a value larger than Long.MAX_VALUE.

  • Lines 10–15: We demonstrate various arithmetic operations using BigInteger methods like add, subtract, multiply, divide, and remainder.

  • Lines 17–21: BigInteger can handle arbitrarily large numbers, these operations are performed without overflow, and the results are printed.

Conclusion

By using the BigInteger class, we can handle very large numbers and perform arithmetic operations without worrying about overflow, which is a limitation with primitive data types like int and long.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved