Step 1 of 5 · Reading · ~4 min
Learn
First Steps
Numbers and Arithmetic
Lua has a single number type with two internal subtypes: integer and float, both 64-bit. You almost never declare which one you want — the operator decides — but you do need to know which one you ended up with, because it changes what gets printed.
Which operator gives which subtype?
| Expression | Subtype | Prints as |
|---|---|---|
7 + 2 | integer | 9 |
7 - 2 | integer | 5 |
7 * 2 | integer | 14 |
7 % 2 | integer | 1 |
7 // 2 | integer | 3 |
7 / 2 | float | 3.5 |
6 / 2 | float | 3.0 |
2 ^ 10 | float | 1024.0 |
Read the last two rows twice. / always produces a float, even when the division comes out even, and ^ always produces a float. 6 / 2 prints 3.0, not 3. On a byte-exact test, those two characters are the whole difference between accepted and rejected.
print(6 / 2)
print(6 // 2)
print(2 ^ 3)
print(7 % 3)
--> 3.0
--> 3
--> 8.0
--> 1
How do I keep an integer?
// is floor division: divide, then round down. Given two integers it gives back an integer.
print(7 // 2)
print(-7 // 2)
print(math.floor(3.7))
print(math.floor(-3.7))
--> 3
--> -4
--> 3
--> -4
Rounding is toward negative infinity, not toward zero — -7 // 2 is -4, not -3. % is defined to match, so the remainder always carries the sign of the divisor and -7 % 2 is 1. That makes n % 2 == 1 a reliable odd-number test even for negatives, which it is not in C or Java, where -7 % 2 comes out as -1.
The math library
print(math.max(3, 9, 4))
print(math.min(3, 9, 4))
print(math.abs(-5))
print(math.floor(2.5))
print(math.ceil(2.1))
print(math.sqrt(16))
--> 9
--> 3
--> 5
--> 2
--> 3
--> 4.0
math.sqrt is the trap in that list: like /, it always hands back a float, so a perfect square still prints with a .0.
Turning text into numbers
Everything io.read() gives you is a string. tonumber converts it.
print(tonumber("42") + 1)
print(tonumber("3.5"))
print(tonumber("twelve"))
--> 43
--> 3.5
--> nil
tonumber returns nil — not zero, not an error — when the text is not a number. That nil then travels one more line and detonates there instead:
✗ blank or non-numeric input
local n = tonumber(io.read())
print(n * 2)
--> script.lua:2: attempt to perform arithmetic on a nil value (local 'n')
Read the parenthetical first whenever a run blows up. Lua tells you the file, the line, and which value was nil — here it names n directly, which is far more than most languages give you.
Conversion follows the way Lua reads literals, so tonumber("42") is an integer while tonumber("42.0") is a float. Same digits on stdin, different characters on stdout.
Why doesn't 0.1 + 0.2 equal 0.3?
Floats are IEEE 754 doubles, and most decimal fractions have no exact binary form. Lua prints numbers to fourteen significant digits, which politely hides the error — but comparison does not.
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
print(math.abs((0.1 + 0.2) - 0.3) < 1e-9)
--> 0.3
--> false
--> true
✓ compare floats with a tolerance · ✗ compare floats with ==
One more rule worth memorising: equality never converts between strings and numbers, but arithmetic does — and that conversion always lands you in a float.
print("10" == 10)
print("10" + 1)
--> false
--> 11.0
That .0 is the sting. Skipping tonumber feels harmless because the arithmetic still works, but "3" * "4" is 12.0, never 12. The string route is a one-way trip into floats.
Your exercise
Hours and Minutes reads a number of minutes and prints it as whole hours plus the minutes left over.
The starter already converts the input with tonumber(io.read()), so you add the arithmetic and the printing. The mistake the grader will catch is a stray float: route the hours through / and 125 minutes prints 2.0 h 5 min instead of 2 h 5 min, failing every test. Remember which operators keep integers, and which one answers "how many are left over".
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…