Skip to content

Rust Type Casting

Rust won’t automatically convert one type into another for you — if you mix an i32 and an f64 in the same expression, it won’t compile. You have to convert explicitly. This is on purpose: silent conversions are a common source of bugs in other languages.

Use the as keyword to cast one number type into another:

fn main() {
let x: i32 = 10;
let y: f64 = x as f64; // i32 -> f64
println!("{y}");
}
▶ Try it Yourself

This matters more than it looks — try dividing two integers without casting, and you’ll get integer division instead of the decimal result you probably wanted:

fn main() {
let a = 10;
let b = 3;
println!("{}", a / b); // 3 (integer division)
println!("{}", a as f64 / b as f64); // 3.3333333333333335
}
▶ Try it Yourself

Casting from a bigger type to a smaller one (like i32 to u8) doesn’t fail — it just truncates, which can give you a surprising result:

fn main() {
let big: i32 = 300;
let small = big as u8; // u8 only holds 0-255
println!("{small}"); // 44, not 300 — it wrapped around
}
▶ Try it Yourself

as works with a few more types than whole numbers. Each one has a rule worth knowing:

fn main() {
println!("{}", 3.99_f64 as i32); // 3: the decimals are cut off
println!("{}", -3.99_f64 as i32); // -3: cut toward zero, not down
println!("{}", 3.99_f64.round() as i32); // 4: round first if you want that
println!("{}", 300.0_f64 as u8); // 255: too big, so it stops at the max
println!("{}", -5.0_f64 as u8); // 0: too small, so it stops at the min
println!("{}", 'A' as u32); // 65: a char's code number
println!("{}", 97_u8 as char); // a: and back again
println!("{}", true as i32); // 1 (false would be 0)
}

Output:

3
-3
4
255
0
65
a
1
▶ Try it Yourself

A few things to take away:

  • Float to integer throws away everything after the decimal point. It doesn’t round. Call .round() first if you want the nearest whole number.
  • Out-of-range floats are clamped to the nearest value that fits (300.0 becomes 255 in a u8). That’s different from integers, which wrap around (300 became 44 above).
  • Characters have a number behind them (their Unicode code point). 'A' as u32 gives 65. Only a u8 can be cast straight back to a char; for bigger numbers you’d use char::from_u32, because not every number is a valid character.
  • Booleans turn into 1 or 0. The other direction doesn’t work: 1 as bool won’t compile. Use a comparison like n != 0 instead.

Casting with as only works between number types. To turn text into a number — say, something typed by a user — use .parse():

fn main() {
let text = "42";
let number: i32 = text.parse().expect("not a valid number");
println!("{}", number + 8);
}

Output:

50
▶ Try it Yourself

.parse() can fail (what if the text isn’t a number at all?), so it returns a Result rather than the number directly. We haven’t covered Result yet — for now, .expect("message") is a simple way to say “crash with this message if it fails.” You’ll see the proper way to handle it on the Result page.

Going the other way is simpler — almost every type can turn into a String with .to_string():

fn main() {
let number = 42;
let text = number.to_string();
println!("{}", text + "!");
}
▶ Try it Yourself

Store three test scores as i32 values: 7, 8 and 10. Print their sum, then their average with two decimal places. Hint: if you divide two integers you get 8, not 8.33, so cast the sum to f64 first. {:.2} prints two decimals.

Show solution
fn main() {
let a: i32 = 7;
let b: i32 = 8;
let c: i32 = 10;
let sum = a + b + c;
let average = sum as f64 / 3.0; // 25.0 / 3.0, not 25 / 3
println!("sum: {sum}");
println!("average: {:.2}", average);
}

Output:

sum: 25
average: 8.33
▶ Try it Yourself

A shop gives you the price as text, "4.50", and the quantity as an i32, 3. Turn the text into an f64, multiply by the quantity, and print Total: 13.5. Hint: you need both tools from this page: .parse() for the text and as f64 for the quantity.

Show solution
fn main() {
let price_text = "4.50";
let quantity: i32 = 3;
let price: f64 = price_text.parse().expect("not a valid price");
let total = price * quantity as f64; // f64 * f64
println!("Total: {total}");
}

Output:

Total: 13.5
▶ Try it Yourself

Without as f64, Rust would refuse to multiply an f64 by an i32, because it never mixes number types for you.

  • Rust never converts types automatically — you always cast explicitly.
  • Use as to convert between number types: x as f64, x as u8.
  • Casting down to a smaller type truncates silently — it won’t error, so be careful.
  • Float to integer cuts off the decimals (use .round() first to round). char and bool can be cast to numbers too.
  • Use .parse() to turn text into a number, and .to_string() to go the other way.

Quick check

1. What happens when you divide two integers like 10 / 3 in Rust without casting?

2. What happens when you cast 300_i32 as u8?

3. What does .parse() return when converting a string to a number, since the conversion can fail?

Score: 0 / 3