Pocket Studio Academy
HomePart 11.4

Math, operators and integer division

Free lesson8 min read·4 questions

Kotlin's arithmetic looks exactly like school maths until one rule bites: dividing two whole numbers throws the fraction away. Learn the operators, the order they run in, and the trap that has bitten every programmer alive.

Seven sweets, two friends

You have seven sweets and two friends. How many does each friend get?

Three. And there is one left over, because you cannot cut a sweet in half without an argument.

Every child works this out without being taught. Kotlin does exactly the same thing, and every programmer is surprised by it once. Here is the line that surprises them:

kotlin
println(7 / 2)

That prints 3. Not 3.5. Not 4. Just 3.

By the end of this lesson you will know precisely why, and you will never be caught by it again.

Think of it like this

Think of a vending machine that only takes whole coins.

You feed it a five-pound note for a £2 drink. It gives you two drinks and £1 change. It does not give you two and a half drinks, because half a drink is not a thing the machine can produce.

is that machine. Ask a whole number to be split by another whole number and Kotlin hands back a whole number — how many fit — and keeps the leftovers separately. The leftovers are what % is for.

The five arithmetic operators

An is a symbol that does something to values. Kotlin's arithmetic set is short:

OperatorDoes7 and 2 give
+Adds9
-Subtracts5
*Multiplies14
/Divides3
%Remainder1

The first three hold no surprises. The last two are the lesson.

Why / behaves like that

Kotlin's rule is simple once you say it out loud:

divided by Int gives an Int.

There is no room in an Int for a decimal point, so the fractional part is thrown away. Kotlin does not round — it truncates, meaning it chops towards zero:

kotlin
1println(7 / 2)      // 3
2println(9 / 10)     // 0
3println(-7 / 2)     // -3

Look at 9 / 10 for a second. Ten does not fit into nine at all, so the answer is zero. That line has silently ruined many a percentage calculation.

And -7 / 2 is -3, not -4. Truncating towards zero means the answer moves up for negatives. Kotlin never rounds down and never rounds to nearest — it always chops.

Getting the decimal answer

Make at least one side a and Kotlin gives you a Double back:

kotlin
1println(7 / 2.0)             // 3.5
2println(7.0 / 2)             // 3.5
3val a = 7
4val b = 2
5println(a.toDouble() / b)    // 3.5

That third form is the one you will use in real code, because your values usually arrive as Int from somewhere else.

Careful

The most common version of this bug hides inside a longer sum:

kotlin
1val done = 3
2val total = 4
3val percent = done / total * 100

percent is 0. Kotlin does 3 / 4 first, which is 0, then multiplies zero by a hundred. Fix it by converting first: done.toDouble() / total * 100, which gives 75.0.

The remainder operator

% gives what is left over. It is far more useful than it sounds:

kotlin
1println(7 % 2)      // 1
2println(10 % 5)     // 0
3println(13 % 5)     // 3

Two everyday jobs for it:

  • Is this number even? n % 2 == 0 is true for even numbers.
  • Wrap a counter round. If you have six dice faces and a counter that keeps climbing, counter % 6 always lands between 0 and 5.

The name to know is , though most people just say "mod".

Order of operations

Kotlin follows the same order you learnt at school: multiply and divide before add and subtract, brackets first.

kotlin
1println(2 + 3 * 4)      // 14, not 20
2println((2 + 3) * 4)    // 20

When a line gets long, add brackets even where they are not strictly needed. They cost nothing and they tell the next reader what you meant.

Note

^ is not "to the power of" in Kotlin. For squaring, just multiply: n * n. For anything larger, Math.pow(2.0, 10.0) does the job and returns a Double.

Shorthand for changing a var

These four lines all add ten to a score, and all of them are common in real code:

kotlin
1var score = 0
2score = score + 10
3score += 10
4score++

+= means "add this to what is already there". The family is +=, -=, *=, /= and %=. score++ is a special shorthand for score += 1, used constantly in loops.

All of these change the value, so they only work on a . Try them on a and you get Val cannot be reassigned.

The whole lesson in nine lines

Try it in Pocket Studio
  1. Open Pocket Studio, tap Projects, open KotlinLab, and open Lab.kt.
  2. Clear the inside of main and type in the program from the walkthrough above.
  3. Tap Run. The Output panel should read 3, 1, 3.5, 11 — one per line.
  4. Add one line before the closing bracket: println(9 / 10). Run it. It prints 0. Sit with that for a moment; it is the single most expensive line in this lesson.
  5. Change it to println(9.0 / 10) and run again. Now it prints 0.9.
  6. Add println(-7 / 2). Run. It prints -3, because chopping moves towards zero.
  7. Last one: change var score = 0 to val score = 0 and run. Read the error, then change it back. Shorthand like += still counts as changing a name.
Error Doctor5 common errors
e: Type mismatch: inferred type is Double but Int was expected
MeansSomething on the right of the = produced a decimal, but the name on the left was declared Int. Usually one value in the sum was a Double.
FixEither declare the name as Double, or finish the sum with .toInt() if you genuinely want the fraction thrown away.
e: Val cannot be reassigned
MeansYou used +=, -= or ++ on a name declared with val. All three change the value, which val forbids.
FixChange the declaration to var. If it should not change, the error has found a real bug in the line that modifies it.
e: The integer literal does not conform to the expected type Double
MeansYou declared a Double but wrote a whole number: val rate: Double = 5.
FixWrite 5.0. Kotlin will not silently promote the literal for you, because being explicit here prevents worse confusion later.
Exception in thread "main" java.lang.ArithmeticException: / by zero
MeansYour code divided an Int by zero while running. This one is not caught at build time — it crashes the program.
FixCheck the divisor before dividing: if (friends > 0) { ... }. Note that dividing a Double by zero does not crash — it produces Infinity, which is its own kind of nasty surprise.
e: Expecting an expression
MeansAn operator has nothing to work on — usually a stray + at the end of a line, or an empty pair of brackets.
FixRead the line from left to right. Every +, -, *, / and % needs a value on both sides.
Recap
  • The are +, -, *, / and %, and they follow the school order: brackets, then multiply and divide, then add and subtract.
  • The fraction is chopped off, not rounded, and it chops towards zero — so -7 / 2 is -3.
  • Convert one side with .toDouble() when you want the decimal answer, and convert before the rest of the sum, not after.
  • % gives the : handy for "is it even?" and for wrapping counters round.
  • +=, -= and ++ are shorthand for changing a value, and only work on a .
  • Next: you have values and you can do sums with them. Time to make the program choose what to do — if and else.