Rust 类型转换
Rust 不会自动帮你把一种类型转换成另一种:如果在同一个表达式里混用 i32 和 f64,代码就编译不过。你必须显式地转换。这是有意为之的:在其他语言里,悄无声息的类型转换是 bug 的常见来源。
用 as 在数字类型之间转换
Section titled “用 as 在数字类型之间转换”用 as 关键字把一种数字类型转换(cast)成另一种:
fn main() { let x: i32 = 10; let y: f64 = x as f64; // i32 -> f64
println!("{y}");}这件事比看上去更重要。试试不做转换直接让两个整数相除,你得到的是整数除法,而不是你想要的小数结果:
fn main() { let a = 10; let b = 3;
println!("{}", a / b); // 3(整数除法) println!("{}", a as f64 / b as f64); // 3.3333333333333335}向下转换可能丢失数据
Section titled “向下转换可能丢失数据”把大类型转换成小类型(比如 i32 转 u8)不会报错,它只会截断,结果可能会吓你一跳:
fn main() { let big: i32 = 300; let small = big as u8; // u8 只能存 0-255 println!("{small}"); // 44,不是 300:它绕回去了}转换浮点数、字符和布尔值
Section titled “转换浮点数、字符和布尔值”as 不只适用于整数,还能处理另外几种类型。每一种都有一条值得记住的规则:
fn main() { println!("{}", 3.99_f64 as i32); // 3:小数部分直接被砍掉 println!("{}", -3.99_f64 as i32); // -3:向零截断,而不是向下取整 println!("{}", 3.99_f64.round() as i32); // 4:想四舍五入就先调用 round println!("{}", 300.0_f64 as u8); // 255:太大,停在最大值 println!("{}", -5.0_f64 as u8); // 0:太小,停在最小值 println!("{}", 'A' as u32); // 65:char 对应的编号 println!("{}", 97_u8 as char); // a:再转回来 println!("{}", true as i32); // 1(false 是 0)}输出:
3-34255065a1要点如下:
- 浮点数转整数会扔掉小数点后的所有内容,不会四舍五入。想得到最接近的整数,先调用
.round()。 - 超出范围的浮点数会被限制(clamp)到能放下的最接近的值(
300.0转成u8变成255)。这和整数不同,整数会绕回(上面的300变成了44)。 - 字符背后都有一个数字(它的 Unicode 码位)。
'A' as u32得到65。只有u8能直接转换回char;更大的数字要用char::from_u32,因为不是每个数字都对应一个有效字符。 - 布尔值会变成
1或0。反过来不行:1 as bool无法编译,要改用n != 0这样的比较。
把字符串解析成数字
Section titled “把字符串解析成数字”as 只能在数字类型之间转换。要把文本(比如用户输入的内容)变成数字,用 .parse():
fn main() { let text = "42"; let number: i32 = text.parse().expect("不是有效的数字");
println!("{}", number + 8);}输出:
50.parse() 可能会失败(万一文本根本不是数字呢?),所以它返回的是一个 Result,而不是直接返回数字。我们还没讲到 Result,目前可以把 .expect("提示信息") 理解为“如果失败,就带着这条信息崩溃”。正确的处理方式会在 Result 一课里讲。
把数字转成字符串
Section titled “把数字转成字符串”反方向要简单得多:几乎所有类型都能用 .to_string() 变成 String:
fn main() { let number = 42; let text = number.to_string(); println!("{}", text + "!");}1. 平均分
Section titled “1. 平均分”用 i32 存三次考试的分数:7、8 和 10。打印它们的总和,再打印保留两位小数的平均分。提示:两个整数相除得到的是 8 而不是 8.33,所以要先把总和转换成 f64。{:.2} 会打印两位小数。
查看答案
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,而不是 25 / 3
println!("总分:{sum}"); println!("平均分:{:.2}", average);}输出:
总分:25平均分:8.332. 从文本算出价格
Section titled “2. 从文本算出价格”商店给你的价格是文本 "4.50",数量是 i32 类型的 3。把文本转成 f64,乘以数量,打印出 总价:13.5。提示:这一课的两个工具都要用上:文本用 .parse(),数量用 as f64。
查看答案
fn main() { let price_text = "4.50"; let quantity: i32 = 3;
let price: f64 = price_text.parse().expect("不是有效的价格"); let total = price * quantity as f64; // f64 * f64
println!("总价:{total}");}输出:
总价:13.5如果没有 as f64,Rust 会拒绝把 f64 和 i32 相乘,因为它从不替你混用数字类型。
- Rust 从不自动转换类型,你总是要显式转换。
- 用
as在数字类型之间转换:x as f64、x as u8。 - 向下转换成更小的类型会悄悄截断,不会报错,所以要小心。
- 浮点数转整数会砍掉小数部分(想四舍五入就先用
.round())。char和bool也能转换成数字。 - 用
.parse()把文本变成数字,用.to_string()反过来转换。
小测验
1. 在 Rust 里不做转换,直接计算 10 / 3 这样的两个整数相除,会怎样?
2. 把 300_i32 用 as 转换成 u8,会发生什么?
3. 因为转换可能失败,用 .parse() 把字符串转成数字时,它返回什么?
得分: 0 / 3
- 类型转换 — 通过例子学 Rust:大量可运行的
as转换示例,注释里写明了每一个的结果。 - Type cast expressions — The Rust Reference(英文):哪些转换是允许的,以及每种转换的精确规则,一览表。
- 字符串的转换 — 通过例子学 Rust:更深入地介绍
.to_string()和.parse()。 TryFrom— 标准库文档(英文):值可能放不下时,就用这种带检查的转换(u8::try_from(...))。- Numeric Types — The Rust Reference(英文):每种整数和浮点类型的大小与取值范围。