Reading — step 1 of 5
Learn
Numbers and Math
Rust's arithmetic is strict in exactly the places other languages are sloppy — and every strictness maps to a bug you now won't have. Three rules cover the territory.
Rule 1: types never mix silently
let a: i32 = 3;
let b: f64 = 1.5;
a + b // ERROR: cannot add `f64` to `i32`
a as f64 + b // 4.5 — conversion written where reviewers can see it
Even i32 + i64 refuses to compile. as is the quick cast — and it's explicitly lossy when narrowing (300_i32 as u8 is 44; it truncates bits, no questions asked), which is why it's reserved for cases you've thought about. That noisiness is the point: in Rust, every place precision could be lost has an as you can grep for.
Rule 2: integer and float division are different operations
7 / 2 // 3 — integer division truncates toward zero
7 % 2 // 1 — remainder
7.0 / 2.0 // 3.5 — float division
Same as Go, same trap: 99 / 100 == 0, and every percentage calculation on integers is wrong until you convert: a as f64 / b as f64. The % operator earns its keep in the classic places — divisibility (n % 3 == 0), wraparound (i % len), digit peeling (n % 10, n / 10).
Rule 3: overflow is a bug, and Rust treats it like one
An i32 maxes out at 2,147,483,647. Add one more and:
- Debug builds panic:
attempt to add with overflow— loud, immediate, at the exact line. - Release builds wrap (for speed), like C — but you're expected to have caught it in debug.
When overflow behavior is intentional, Rust makes you say which kind: a.wrapping_add(b) (wrap around), a.checked_add(b) (returns an Option — None on overflow), a.saturating_add(b) (clamps at the max). Hash functions want wrapping; account balances want checked. The method name documents the decision — this is very Rust.
Floats: the universal caveats, plus methods
f64 is IEEE-754, so the classics apply: 0.1 + 0.2 != 0.3, never == floats (compare (a - b).abs() < 1e-9), never floats for money. What's different is ergonomics — math lives in methods on the numbers themselves:
let x: f64 = 2.0;
x.sqrt() // 1.4142135623730951
x.powi(10) // 1024.0 (integer exponent)
x.powf(0.5) // sqrt, via float exponent
(-3.5_f64).abs() // 3.5
9_i32.pow(2) // 81 — integers have pow too
(That 2.0_f64 / 9_i32 suffix syntax pins a literal's type when inference needs a hint — and underscores work as digit separators anywhere: 1_000_000.)
Your exercise: Rectangle Area
Read width and height, multiply, print. The engineering content is entirely in the edges: decide i64 vs f64 from the problem's examples (are inputs 12 or 2.5? is expected output 24 or 24.00?), reuse the stdin-parsing pattern from last lesson, and format output to match exactly — {} prints 24.0 for a float where a grader may want 24.00 ({:.2} — next lesson makes formatting systematic). One multiplication, three decisions; that ratio is what real programming feels like.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…