Using large numbers in Kotlin
As you might remember, the standard primitive integer types cannot store extremely large numbers. It is not possible to assign such a large number to a variable of the type Int (or even Long):
val y: Int = 62957291795228763406253098 // compilation error: The value is out of range
This is also the reason why operations with numbers can sometimes lead to overflow. Let's look at the example below:
var a: Int = Int.MAX_VALUE // 2147483647
a += 2 // -2147483647
Luckily for us, the Java Class Library provides a class called BigInteger for processing very large numbers (both positive and negative). The size of a stored number is limited only by the available amount of memory. So, when you use Kotlin/JVM environment, you can use BigIntegers.
The BigInteger class is immutable which means functions and operators of the class return new instances instead of changing existing ones.
Although this type can store any integers, including small numbers, you should not use BigInteger unless you absolutely have to. There is always a performance hit associated with its use. BigInteger operations are slower than operations on built-in integer types.
Creating objects of BigInteger
The class BigInteger belongs to the java.math package. We import it by writing the following statement:
import java.math.BigInteger
Here we can see an instance of the class that stores the large number that we have met before:
val number = BigInteger("62957291795228763406253098")
It is also possible to create an instance by passing a Long value to the valueOf function:
val number = BigInteger.valueOf(1000000000)
Moreover, the class has several useful constants. Using a specific constant is slightly faster than creating an extra object:
val zero = BigInteger.ZERO // 0
val one = BigInteger.ONE // 1
val ten = BigInteger.TEN // 10
Also, there is a handy way to convert standard numbers and strings to BigInteger:
val numToBigInt = 1234.toBigInteger()
val strToBigInt = "1234".toBigInteger()Arithmetic operations
You can use operators to perform arithmetic operations with BigInteger:
val eleven = ten + one // 10 + 1 = 11
val nine = ten - one // 10 - 1 = 9
val oneHundredTen = ten * eleven // 10 * 11 = 110
val twelve = oneHundredTen / nine // integer division = 12
val two = oneHundredTen % nine // remainder = 2
The unary minus operator returns a new BigInteger that has an opposite sign.
val minusOne = -one // -1
Also, it is possible to use increment (++) and decrement (--) operators in prefix and postfix forms.
Functions of BigInteger
The divideAndRemainder function returns an array consisting of two numbers: the result of integer division and the remainder:
val (result, remainder) = oneHundredTen.divideAndRemainder(nine) // 12 and 2
The class also provides functions for performing more complex math operations. The abs function returns a new BigInteger whose value is the absolute value of this BigInteger:
val number = BigInteger("-8")
println(number.abs()) // 8
The gcd function returns the greatest common divisor of two numbers.
val eight = BigInteger.valueOf(8)
val six = BigInteger.valueOf(6)
println(eight.gcd(six)) // 2Conclusion
Now you know that Kotlin supports the Java type for handling arbitrary-precision integers. Let's practice!