Skip to content

基本类型

> 掌握整数、浮点数、布尔和字符四种标量类型的范围、用法与类型转换。

整数类型

整数类型全览

Rust 的整数类型按位宽是否有符号分类:

┌────────────────────────────────────────────────────┐
│                  整数类型表                         │
├──────────┬─────────────────────────────────────────┤
│  位宽    │  有符号 (负数)  │  无符号 (仅非负)      │
├──────────┼─────────────────┼───────────────────────┤
│  8-bit   │  i8             │  u8                   │
│  16-bit  │  i16            │  u16                  │
│  32-bit  │  i32            │  u32                  │
│  64-bit  │  i64            │  u64                  │
│  128-bit │  i128           │  u128                 │
│  指针宽  │  isize          │  usize                │
└──────────┴─────────────────┴───────────────────────┘

记忆技巧:
• i = integer(整数)
• u = unsigned(无符号)
• 数字 = 位数(8/16/32/64/128)

数值范围

类型最小值最大值实际应用场景
i8-128127温度传感器读数
u80255RGB 颜色值、ASCII 字符
i16-32,76832,767音频采样
u16065,535像素坐标
i32-21 亿21 亿默认整数类型
u32042 亿IPv4 地址
i64-9×10¹⁸9×10¹⁸时间戳、大金额
u6401.8×10¹⁹文件 ID
isize/usize依赖平台依赖平台数组索引、集合大小

代码示例

rust
fn main() {
    // 默认类型推断(i32)
    let default_num = 42;
    println!("默认类型:{:?}", std::any::type_name_of_val(&default_num));
    // 输出:i32

    // 显式类型标注
    let small: i8 = 100;
    let medium: i16 = 30000;
    let large: i64 = 1_000_000_000_000;

    // 不同进制表示
    let decimal = 42;         // 十进制
    let hex = 0x2A;           // 十六进制:2*16 + 10 = 42
    let octal = 0o52;         // 八进制:5*8 + 2 = 42
    let binary = 0b101010;    // 二进制:32+8+2 = 42

    // 验证它们都相等
    assert_eq!(decimal, hex);
    assert_eq!(decimal, octal);
    assert_eq!(decimal, binary);

    // 下划线分隔符(提高可读性)
    let one_million = 1_000_000;
    let spaced = 1_00_00_00;  // 印度数字系统写法

    println!("十进制:{}", decimal);
    println!("十六进制:0x{:X}", hex);
    println!("八进制:0o{:o}", octal);
    println!("二进制:0b{:b}", binary);
    println!("一百万:{}", one_million);
}
▶ Run

整数溢出详解

rust
fn main() {
    let max_u8: u8 = 255;

    // ❌ 这会 panic(调试模式)
    // let overflow = max_u8 + 1;

    // ✅ 安全的溢出处理方法

    // 方法 1:checked_add - 返回 Option
    match max_u8.checked_add(1) {
        Some(result) => println!("结果:{}", result),
        None => println!("溢出!"),
    }

    // 方法 2:wrapping_add - 回绕
    let wrapped = max_u8.wrapping_add(1);
    println!("回绕结果:{}", wrapped);  // 0

    // 方法 3:saturating_add - 饱和(卡在最大值)
    let saturated = max_u8.saturating_add(1);
    println!("饱和结果:{}", saturated);  // 255

    // 方法 4:overflowing_add - 返回 (值,是否溢出)
    let (result, overflowed) = max_u8.overflowing_add(1);
    println!("值:{},溢出:{}", result, overflowed);
}
▶ Run

类型转换(as)

rust
fn main() {
    // 小 → 大(安全)
    let small: u8 = 42;
    let large: i32 = small as i32;
    println!("小转大:{}", large);

    // 大 → 小(可能丢失数据!)
    let big: u16 = 1000;
    let truncated: u8 = big as u8;
    // 1000 的二进制:00000011 11101000
    // 截断低 8 位:11101000 = 232
    println!("大转小:{} → {}", big, truncated);

    // 负数转无符号(小心!)
    let negative: i8 = -1;
    // -1 的补码表示:11111111
    // 解释为 u8: 255
    let unsigned = negative as u8;
    println!("负数转无符号:{} → {}", negative, unsigned);

    // 验证
    assert_eq!(-1i8 as u8, 255);
}
▶ Run

浮点类型

f32 vs f64

rust
fn main() {
    // f64 是默认类型(64 位,约 15-17 位有效数字)
    let default_float = 3.14159265358979;

    // f32(32 位,约 6-7 位有效数字)
    let half_precision: f32 = 3.141593;

    println!("f64 类型:{:?}", std::any::type_name_of_val(&default_float));
    println!("f32 类型:{:?}", std::any::type_name_of_val(&half_precision));

    // 精度差异演示
    let precise: f64 = 0.1 + 0.2;
    let less_precise: f32 = 0.1f32 + 0.2f32;

    println!("f64: 0.1 + 0.2 = {:.20}", precise);
    println!("f32: 0.1 + 0.2 = {:.20}", less_precise);
}
▶ Run

特殊浮点值

rust
fn main() {
    // 无穷大
    let inf = f64::INFINITY;
    println!("正无穷:{}", inf);
    println!("1.0 / 0.0 = {}", 1.0 / 0.0);  // inf

    // 负无穷
    let neg_inf = f64::NEG_INFINITY;
    println!("负无穷:{}", neg_inf);
    println!("-1.0 / 0.0 = {}", -1.0 / 0.0);  // -inf

    // NaN(Not a Number)
    let nan = f64::NAN;
    println!("NaN: {}", nan);
    println!("0.0 / 0.0 = {}", 0.0 / 0.0);  // NaN

    // NaN 的特殊性:不等于任何值,包括自己
    println!("NaN == NaN: {}", nan == nan);  // false
    println!("NaN.is_nan(): {}", nan.is_nan());  // true

    // 其他特殊值
    println!("最大值:{}", f64::MAX);
    println!("最小值:{}", f64::MIN);
    println!("最小正数:{}", f64::MIN_POSITIVE);
    println!("机器 epsilon: {}", f64::EPSILON);
}
▶ Run

浮点数运算

rust
fn main() {
    let x = 10.0;
    let y = 3.0;

    // 基本运算
    println!("{} + {} = {}", x, y, x + y);
    println!("{} - {} = {}", x, y, x - y);
    println!("{} * {} = {}", x, y, x * y);
    println!("{} / {} = {}", x, y, x / y);
    println!("{} % {} = {}", x, y, x % y);

    // 常用方法
    println!("x.powf(2.0) = {}", x.powf(2.0));    // 100.0
    println!("x.sqrt() = {}", x.sqrt());          // 3.162...
    println!("x.cbrt() = {}", x.cbrt());          // 2.154...
    println!("x.exp() = {}", x.exp());            // e^10
    println!("x.ln() = {}", x.ln());              // ln(10)
    println!("x.log10() = {}", x.log10());        // 1.0
    println!("x.sin() = {}", x.sin());
    println!("x.cos() = {}", x.cos());

    // 取整方法
    let num = 3.7;
    println!("{} 的取整:", num);
    println!("  floor (向下): {}", num.floor());    // 3.0
    println!("  ceil  (向上): {}", num.ceil());     // 4.0
    println!("  round (四舍五入): {}", num.round());  // 4.0
    println!("  trunc (截断): {}", num.trunc());    // 3.0
    println!("  fract (小数部分): {}", num.fract());  // 0.7
}
▶ Run

浮点数比较的正确方式

rust
fn main() {
    // ❌ 错误:直接比较浮点数
    let a = 0.1 + 0.1 + 0.1;
    let b = 0.3;
    // println!("{}", a == b);  // false! 因为浮点精度问题

    // ✅ 正确:比较差值是否在误差范围内
    let epsilon = f64::EPSILON;  // 约 2.2e-16
    let almost_equal = (a - b).abs() < epsilon;
    println!("a ≈ b: {}", almost_equal);  // 可能还是 false

    // 使用更大的容差
    let tolerance = 1e-10;
    println!("|a - b| = {:.20}", (a - b).abs());
    println!("a ≈ b (tolerance=1e-10): {}", (a - b).abs() < tolerance);

    // 实际项目中常用的 epsilon
    const FLOAT_EPSILON: f64 = 1e-9;
    fn float_eq(a: f64, b: f64) -> bool {
        (a - b).abs() < FLOAT_EPSILON
    }
    println!("float_eq(0.3, 0.1+0.1+0.1): {}", float_eq(0.3, a));
}
▶ Run

布尔类型

布尔运算

rust
fn main() {
    let t = true;
    let f = false;

    // 逻辑与(AND)- 两个都为真才为真
    println!("true && true = {}", t && t);
    println!("true && false = {}", t && f);

    // 逻辑或(OR)- 一个为真就为真
    println!("true || false = {}", t || f);
    println!("false || false = {}", f || f);

    // 逻辑非(NOT)- 取反
    println!("!true = {}", !t);
    println!("!false = {}", !f);
}
▶ Run

短路求值(重要!)

rust
fn main() {
    // AND 短路:第一个为假,不计算第二个
    let result = false && {
        println!("这行不会打印");
        true
    };
    println!("result = {}", result);

    // OR 短路:第一个为真,不计算第二个
    let result = true || {
        println!("这行也不会打印");
        true
    };
    println!("result = {}", result);

    // 实际应用:安全检查
    let age: u8 = 25;
    let has_id = true;

    // 只有 age >= 18 时才会检查 has_id
    let can_enter = age >= 18 && has_id;
    println!("可以进入:{}", can_enter);

    // 链式调用中的短路
    let maybe_name: Option<String> = Some("Alice".to_string());
    // is_some() 为真时,才会执行 unwrap()
    let is_alice = maybe_name.is_some() && maybe_name.unwrap() == "Alice";
    println!("是 Alice: {}", is_alice);
}
▶ Run

布尔值在实际场景中的应用

rust
fn main() {
    // 标志位
    let is_logged_in = true;
    let has_permission = false;

    // 条件组合
    let can_access = is_logged_in && has_permission;
    println!("可以访问:{}", can_access);

    // 切换状态
    let mut light_on = true;
    light_on = !light_on;  // 切换开关
    println!("灯开着:{}", light_on);

    // 布尔值转整数
    println!("true as u8 = {}", true as u8);   // 1
    println!("false as u8 = {}", false as u8); // 0
}
▶ Run

字符类型

char 基础

rust
fn main() {
    // 单引号!不是双引号
    let letter_a = 'a';
    let emoji_crab = '🦀';
    let japanese = 'あ';
    let hebrew = 'ש';

    println!("字母:{}", letter_a);
    println!("螃蟹 emoji: {}", emoji_crab);
    println!("日文:{}", japanese);
    println!("希伯来文:{}", hebrew);

    // char 始终是 4 字节(Unicode 标量值)
    println!("char 大小:{} 字节", std::mem::size_of::<char>());

    // 转义字符
    let tab = '\t';
    let newline = '\n';
    let backslash = '\\';
    let single_quote = '\'';
    let null = '\0';

    println!("制表符:[{}]", tab);
    println!("反斜杠:{}", backslash);
}
▶ Run

Unicode 详解

rust
fn main() {
    // Unicode 码点转义
    let heart = '\u{2764}';       // ❤
    let crab = '\u{1F980}';       // 🦀
    let rocket = '\u{1F680}';     // 🚀
    let smiling_face = '\u{263A}'; // ☺

    println!("爱心:{} (U+2764)", heart);
    println!("螃蟹:{} (U+1F980)", crab);

    // char 转 u32(获取码点值)
    let a_code = 'A' as u32;
    println!("'A' 的 Unicode 码点:U+{:04X}", a_code);

    // 中文字符
    let zhong = '中';
    println!("'中' 的码点:U+{:04X}", zhong as u32);

    // char 方法
    let c = 'A';
    println!("'{}' 是字母:{}", c, c.is_alphabetic());
    println!("'{}' 是数字:{}", c, c.is_numeric());
    println!("'{}' 是空白:{}", c, c.is_whitespace());
    println!("'{}' 转小写:{}", c, c.to_lowercase());

    let space = ' ';
    println!("空格是空白:{}", space.is_whitespace());

    let num = '5';
    println!("'5' 是数字:{}", num.is_numeric());
    println!("'5' 转数字:{}", num.to_digit(10).unwrap());
}
▶ Run

小结

  • 整数类型:i8/u8i128/u128isize/usize 随平台变化
  • 浮点类型:f32(单精度)和 f64(双精度,默认)
  • 布尔类型:bool,只有 true/false,不能隐式转换为整数
  • 字符类型:char,Unicode 标量值,占 4 字节,用单引号

练习题

详见:练习题