Skip to content
Lesson 3 of 19

Step 1 of 5 · Reading · ~3 min

Learn

Getting Started

Numbers and Math

Kotlin's arithmetic looks like every other C-family language — + - * / % — and then springs two traps that account for most beginner bugs. Learn them now and you never write them.

Trap 1: integer division throws the remainder away

If both sides of / are integers, the result is an integer. Kotlin does not round; it chops towards zero.

fun main() {
    val total = 17
    val parts = 5

    println(total / parts)
    println(total % parts)
    println(total.toDouble() / parts)
}

//> 3
//> 2
//> 3.4

17 / 5 is 3 — not 3.4, and not 4. The % operator hands you what fell off the end. To get a fractional answer, at least one side must be a floating-point number, which is exactly what the .toDouble() call is arranging.

✓ Averaging two integers, correctly:

val average = (a + b).toDouble() / 2

✗ The classic: the division happens in Int first and then gets widened, so the fraction is already gone.

val average = ((a + b) / 2).toDouble()

Trap 2: Kotlin never converts numbers for you

Java quietly widens an int into a double. Kotlin refuses. Every change of numeric type is a method call that you write.

From → toCall
IntDoublecount.toDouble()
IntLongcount.toLong()
DoubleIntratio.toInt() — truncates, does not round
anything → textvalue.toString()
text → Inttext.toInt() — throws if the text is not a number

as Double is not an alternative. Int is not a subtype of Double, so the cast does not even compile. It is always .toDouble().

The sizes, and what happens at the edges

TypeBitsRange
Byte8-128 to 127
Short16-32768 to 32767
Int32about plus or minus 2.1 billion
Long64about plus or minus 9.2 quintillion

Overflow is silent. Nothing throws; the value simply wraps round:

fun main() {
    val max = 2147483647
    println(max + 1)
}

//> -2147483648

If a running total might pass two billion, make it a Long before you start adding. Long literals take an L suffix: 3000000000L.

Math functions

import kotlin.math.sqrt
import kotlin.math.abs

fun main() {
    println(sqrt(144.0))
    println(abs(-7))
    println(maxOf(3, 9))
    println(minOf(3, 9))
}

//> 12.0
//> 7
//> 9
//> 3

sqrt wants a Double, which is why the argument is 144.0 and not 144. Notice the result prints as 12.0 — a Double always shows its decimal point, even when the value is whole. That one detail decides whether a graded test passes.

Your exercise

Rectangle Area reads a width and a height on separate lines and prints the area.

Both arrive as Int, so w * h is an Int and prints as 15. The mistake the grader catches is converting somewhere along the way: w.toDouble() * h prints 15.0, the test expects exactly 15, and the comparison fails. Read the two numbers with one readLine() each — they arrive on separate lines, not separated by a space — and print the product with nothing else on the line.

Up nextStrings and TemplatesStrings and Null Safety

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…