Skip to content

Getting started in Kotlin

This tutorial computes with the three number types of Kt-Math from Kotlin code. The same code runs on every target of a multiplatform project: JVM, JavaScript and Kotlin/Native.

Add the dependency

In the build.gradle.kts of a Kotlin Multiplatform project (see the how-to guide for other set-ups):

kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation("io.github.gciatto:kt-math:VERSION")
            }
        }
    }
}

Everything lives in the org.gciatto.kt.math package.

Integers

BigIntegers are created from strings or Kotlin numbers, and support Kotlin's arithmetic and comparison operators:

        val x = BigInteger.of("123456789012345678901234567890")
        val y = 42.toBigInteger()
        assertEquals("5185185138518518513851851851380", (x * y).toString())
        assertEquals("2939447357436801878600823045", (x / y).toString())
        assertEquals("7", (x % 11.toBigInteger()).toString())
        assertEquals("1000", (BigInteger.TEN pow 3).toString())
        assertEquals("ff", 255.toBigInteger().toString(16))
        assertTrue(x > y)
        assertFailsWith<ArithmeticException> { x / BigInteger.ZERO }

Decimals

BigDecimals are exact decimal numbers with a scale (the number of digits after the decimal point): 1.10 and 1.1 are equal in value, but not in scale. Divisions whose result has no exact decimal representation need a MathContext (a precision and a RoundingMode), or a scale and a rounding mode:

        val a = "1.10".toBigDecimal()
        val b = 3.toBigDecimal()
        assertEquals("4.10", (a + b).toString())
        assertEquals("0.3666666667", a.div(b, MathContext(10, RoundingMode.HALF_EVEN)).toString())
        assertEquals("0.37", a.div(b, 2, RoundingMode.HALF_UP).toString())
        assertEquals("1.414213562", 2.toBigDecimal().sqrt(MathContext(10)).toString())
        assertEquals("0.1", 0.1.toBigDecimal().toString()) // the shortest decimal representation of the Double
        assertFailsWith<ArithmeticException> { BigDecimal.ONE / b } // 1/3 has no exact decimal representation

Rationals

BigRationals are fractions of arbitrary-precision numbers: sums, products and quotients are exact, and a decimal approximation is computed only on request:

        val third = "1/3".toBigRational()
        val sum = third + BigRational.valueOf(1, 6)
        assertEquals("1/2", sum.reduce().toRationalString())
        assertEquals("0.3333333333", third.toBigDecimal(MathContext(10)).toString())
        assertEquals(BigRational.ONE, (third * 3).reduce())

Factories and conversions

BigFactory gathers every way of creating numbers, including parsing functions returning null on invalid input; BigFactory.default uses the fastest implementation of the platform. Every number type converts to the others:

        val factory: BigFactory = BigFactory.default // the most efficient implementation for the platform
        assertEquals("-255", factory.parseBigInteger("-ff", radix = 16).toString())
        assertNull(factory.parseBigDecimalOrNull("1..2"))
        val rational = factory.bigRationalOf(BigDecimal.of("1.25"))
        assertEquals("5/4", rational.reduce().toRationalString())
        assertEquals("1", rational.toBigInteger().toString())
        assertEquals("12.34", 1234.toBigInteger().toBigDecimal(scale = 2).toString())

Next steps