本文 AI 產出,尚未審核

Rust 基本語法與變數 — 資料型態(整數、浮點數、布林值、字元)

簡介

在程式語言的世界裡,資料型態是所有變數與常數的根基。Rust 以安全與效能為設計核心,對型別的檢查相當嚴格,這讓開發者能在編譯期即捕捉許多潛在錯誤。了解整數、浮點數、布林值與字元的行為與限制,是寫出正確、可預測程式的第一步。

本單元將帶你一步步認識 Rust 常用的四大基礎型別,並透過實作範例說明它們在真實專案中的應用方式。即使你是剛接觸 Rust 的新手,只要跟著本文的步驟走,也能快速上手,為後續更進階的所有權與錯誤處理打下堅實基礎。

核心概念

1. 整數(Integer)

Rust 提供多種寬度與有號/無號的整數型別,常見的有 i8i16i32i64i128 以及對應的 u8u16u32u64u128。預設情況下,字面值會被推斷為 i32,除非你顯式指定。

1.1 基本宣告與型別推斷

fn main() {
    // 型別推斷為 i32
    let a = 42;
    // 明確指定為 u8
    let b: u8 = 255;
    // i64 範例,使用後綴 `i64`
    let c = 1_000_000i64;

    println!("a = {}, b = {}, c = {}", a, b, c);
}

註解_ 只是一個視覺上的分隔符,編譯器會忽略它,方便閱讀大數字。

1.2 溢位檢查(Overflow)

debug 模式下,Rust 會在執行階段檢查整數溢位;在 release 模式則會採用兩補數的包裹行為(wrap around)。若需要明確的包裹行為,可使用 wrapping_* 方法。

fn main() {
    let max_u8: u8 = u8::MAX; // 255
    // Debug 會 panic,Release 會 wrap
    // let overflow = max_u8 + 1; // 直接加會在 debug 時 panic

    // 使用 wrapping_add 強制包裹
    let wrapped = max_u8.wrapping_add(1);
    println!("wrapped = {}", wrapped); // 0
}

1.3 型別轉換(Casting)

Rust 不允許隱式轉換,必須使用 as 明確轉型。注意在轉型時可能會發生截斷或符號位變化。

fn main() {
    let small: u8 = 200;
    // 轉成 i16,保持數值
    let larger = small as i16;
    // 轉成 i8,會截斷高位
    let truncated = small as i8; // 結果為 -56

    println!("larger = {}, truncated = {}", larger, truncated);
}

2. 浮點數(Floating‑point)

Rust 內建兩種 IEEE‑754 標準的浮點型別:f32(單精度)與 f64(雙精度),預設為 f64。浮點數適合處理科學計算與圖形渲染等需要小數的情境。

2.1 基本使用

fn main() {
    let x = 3.14;          // 推斷為 f64
    let y: f32 = 2.71828; // 明確指定為 f32

    println!("x = {}, y = {}", x, y);
}

2.2 特殊值:NaN 與 Infinity

浮點運算可能產生 NaN(Not a Number) 或正負無限大。使用 is_nan()is_infinite() 來檢測。

fn main() {
    let nan = 0.0_f64 / 0.0;
    let inf = 1.0_f64 / 0.0;

    println!("nan is NaN? {}", nan.is_nan());           // true
    println!("inf is infinite? {}", inf.is_infinite()); // true
}

2.3 精度比較

直接比較兩個浮點數是否相等往往不安全,建議使用容差(epsilon)判斷。

fn approx_eq(a: f64, b: f64, epsilon: f64) -> bool {
    (a - b).abs() < epsilon
}

fn main() {
    let a = 0.1 + 0.2;
    let b = 0.3;
    println!("a == b? {}", approx_eq(a, b, 1e-10));
}

3. 布林值(Boolean)

布林型別只有兩個可能值:truefalse。它是控制流程(ifwhile)的核心。

3.1 基本範例

fn main() {
    let is_rust_fun: bool = true;
    let is_sunny = false; // 型別推斷

    if is_rust_fun && !is_sunny {
        println!("今天寫 Rust,天氣雖然不佳,但仍然很開心!");
    }
}

3.2 與條件運算子結合

Rust 沒有傳統的三元運算子 (?:);可以使用 if 表達式直接回傳值。

fn main() {
    let score = 85;
    let grade = if score >= 60 { "合格" } else { "不合格" };
    println!("成績判定:{}", grade);
}

4. 字元(Char)

Rust 的 char 代表 Unicode scalar value,占 4 個位元組,可直接處理中文、表情符號等多國語言文字。

4.1 單一字元宣告

fn main() {
    let latin = 'R';
    let chinese = '中';
    let emoji = '🚀';

    println!("{} {} {}", latin, chinese, emoji);
}

4.2 迭代字元與字串長度

String&str 以 UTF‑8 編碼儲存,len() 回傳的是位元組長度;若要取得字元數,需要使用 .chars().count()

fn main() {
    let s = "Rust🚀語言";
    println!("位元組長度: {}", s.len());               // 13
    println!("字元數: {}", s.chars().count());        // 5
}

4.3 字元與位元組的轉換

使用 as u32 可取得字元的 Unicode 編碼點,反之則可透過 std::char::from_u32 建立字元。

fn main() {
    let c = '🦀';
    let code = c as u32;
    println!("🦀 的 Unicode 編碼: U+{:X}", code);

    let restored = std::char::from_u32(code).unwrap();
    println!("還原後的字元: {}", restored);
}

常見陷阱與最佳實踐

陷阱 說明 建議的做法
隱式型別推斷 在大型程式中,過度依賴推斷會讓讀者不易判斷變數寬度,尤其是整數。 明確標註 重要變數的型別(如 u64i128),避免未預期的截斷。
整數溢位 Debug 模式會 panic,Release 會包裹,兩者行為不一致。 在可能會溢位的運算使用 checked_*wrapping_*saturating_* 系列方法,並自行處理 Option 結果。
浮點比較 直接 a == b 可能因精度誤差失敗。 使用 容差比較(epsilon)或 approx_eq 函式。
字元 vs 位元組 String::len() 回傳位元組長度,易與字元數混淆。 需要字元數時,使用 s.chars().count();若只關心位元組大小,則直接 len()
布林值的隱晦 把非布林值直接當條件使用會編譯錯誤(Rust 不允許隱式轉換)。 始終使用布林表達式,如 if x > 0 {},而非 if x {}

最佳實踐小結

  1. 顯式型別:在公共 API 或跨平台程式碼中,盡量寫出完整型別。
  2. 錯誤處理:對可能失敗的型別轉換(如 from_u32)使用 matchunwrap_or
  3. 使用標準庫std::num::Wrappingchecked_* 系列提供安全的算術操作,優先考慮。
  4. 文件化:在程式碼註解或 /// 文件中說明為何選擇特定寬度或精度,提升可維護性。

實際應用場景

場景 需要的型別 為何選擇
計算金融利息 i64f64 金額常以最小貨幣單位(如分)存於 i64,最後再轉為 f64 顯示小數點。
圖形渲染座標 f32 大量座標計算,使用單精度可減少記憶體與運算成本,且精度足以滿足螢幕像素。
旗標與權限 u8u32 使用位元運算管理多個布林旗標,u32 能容納 32 個獨立權限。
文字處理(多語系) charString 需要支援中文、日文、表情符號等 Unicode,char 能完整表示單一碼點。
感測器資料 i16u16 大多數硬體感測器回傳 16 位元有號或無號整數,直接對映到相同型別可避免轉換成本。

總結

本篇文章從 整數、浮點數、布林值、字元 四大基礎型別出發,說明了 Rust 如何透過嚴格的型別系統與豐富的標準庫方法,協助開發者寫出安全且效能佳的程式碼。掌握型別推斷與顯式宣告的平衡、了解溢位與精度比較的陷阱、善用 as 轉型與 checked_* 系列函式,都是在實務開發中不可或缺的技巧。

未來當你在撰寫更複雜的資料結構或與外部系統互動時,這些基礎型別的概念將成為你解決問題的根本工具。祝你在 Rust 的旅程中,寫出 安全、快速、易讀 的程式!