型別(數字詳解)
本集目標
認識 Rust 所有的數字型別,以及數字後綴的用法。
正文
上一集我們簡單認識了 i32 和 f64。今天來把 Rust 所有的數字型別都看一遍。
整數型別
Rust 的整數型別分成有號(可以是負數)和無號(只能是正數和零):
| 有號 | 無號 | 位元數 | 範圍(有號) |
|---|---|---|---|
i8 | u8 | 8 | -128 ~ 127 |
i16 | u16 | 16 | -32,768 ~ 32,767 |
i32 | u32 | 32 | 約 ±21 億 |
i64 | u64 | 64 | 超級大 |
i128 | u128 | 128 | 天文數字 |
isize | usize | 看系統 | 64 位元系統 = 64 位元 |
i= integer(整數),u= unsigned(無號)- 數字代表用幾個位元來存——位元越多,能存的數字越大
isize和usize的大小取決於你的系統是 32 位元還是 64 位元(現在幾乎都是 64 位元)
日常用 i32 就夠了。 不確定的時候,用 i32。
浮點數型別
浮點數就是帶小數點的數字,只有兩種:
| 型別 | 精確度 |
|---|---|
f32 | 單精度(精確到約 7 位小數) |
f64 | 雙精度(精確到約 15 位小數) |
日常用 f64 就夠了。 Rust 預設的浮點數就是 f64。
浮點數運算
第 5 集教算術運算的時候,我們都用整數。浮點數一樣可以用 + - * / %,但有一個重要的差別——浮點數除法會保留小數:
fn main() {
let a = 10.0;
let b = 3.0;
println!("{}", a / b); // 3.3333333333333335
println!("{}", a % b); // 1.0
}
還記得第 5 集 10 / 3 的結果是 3(整數除法直接截斷)嗎?浮點數不會截斷,10.0 / 3.0 會得到 3.3333...。
不過浮點數有一個經典的坑——精確度問題:
fn main() {
println!("{}", 0.1 + 0.2); // 0.30000000000000004
}
0.1 + 0.2 不是 0.3!這不是 Rust 的 bug,而是所有程式語言都有的浮點數精確度限制。電腦用二進位存小數,有些十進位小數沒辦法精確表示。知道有這件事就好,不用太擔心。
Rust 怎麼推斷數字型別?
當你寫 let x = 5;,Rust 預設把它當成 i32。
當你寫 let y = 3.14;,Rust 預設把它當成 f64。
但 Rust 不只看數字本身,它也會根據你怎麼使用這個變數來推斷型別。有時候根據上下文,Rust 會推斷出 i32 以外的整數型別。這個之後遇到的時候會更清楚。
不過基本上來說,整數預設就是 i32、浮點數預設就是 f64。
數字後綴(literal suffix)
如果你想要指定型別,除了 let x: i64 = 5; 之外,還有一個更簡潔的寫法——直接在數字後面加型別名稱:
fn main() {
let a = 5i32; // i32
let b = 5u8; // u8
let c = 3.14f64; // f64
let d = 2.0f32; // f32
let e = 100000i64; // i64
println!("{} {} {} {} {}", a, b, c, d, e);
}
5i32 意思就是「5 這個數字,型別是 i32」。數字和型別之間不用空格,直接接在一起。
小提醒
不同型別的數字不能直接混著算:
fn main() {
let a: i32 = 5;
let b: i64 = 10;
println!("{}", a + b); // ❌ 編譯錯誤!i32 和 i64 不能直接相加
}
這是 Rust 的安全設計,Rust 不會自動幫你轉換型別。
重點整理
- 整數分有號(
i8-i128)和無號(u8-u128),日常用i32就夠了 isize和usize的大小取決於系統(64 位元上是 64 位元)- 浮點數有
f32和f64,日常用f64(Rust 預設) - 數字後綴(如
5i32、3.14f64)可以直接指定型別 - 浮點數除法保留小數,但有精確度問題(
0.1 + 0.2 ≠ 0.3) - 不同型別的數字不能直接混著算,Rust 不會自動轉型