基本类型
> 掌握整数、浮点数、布尔和字符四种标量类型的范围、用法与类型转换。
整数类型
整数类型全览
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 | -128 | 127 | 温度传感器读数 |
u8 | 0 | 255 | RGB 颜色值、ASCII 字符 |
i16 | -32,768 | 32,767 | 音频采样 |
u16 | 0 | 65,535 | 像素坐标 |
i32 | -21 亿 | 21 亿 | 默认整数类型 |
u32 | 0 | 42 亿 | IPv4 地址 |
i64 | -9×10¹⁸ | 9×10¹⁸ | 时间戳、大金额 |
u64 | 0 | 1.8×10¹⁹ | 文件 ID |
isize/usize | 依赖平台 | 依赖平台 | 数组索引、集合大小 |
代码示例
rust
▶ Runfn 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);
}整数溢出详解
rust
▶ Runfn 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);
}类型转换(as)
rust
▶ Runfn 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);
}浮点类型
f32 vs f64
rust
▶ Runfn 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);
}特殊浮点值
rust
▶ Runfn 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);
}浮点数运算
rust
▶ Runfn 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
}浮点数比较的正确方式
rust
▶ Runfn 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));
}布尔类型
布尔运算
rust
▶ Runfn 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);
}短路求值(重要!)
rust
▶ Runfn 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);
}布尔值在实际场景中的应用
rust
▶ Runfn 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
}字符类型
char 基础
rust
▶ Runfn 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);
}Unicode 详解
rust
▶ Runfn 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());
}小结
- 整数类型:
i8/u8到i128/u128,isize/usize随平台变化 - 浮点类型:
f32(单精度)和f64(双精度,默认) - 布尔类型:
bool,只有true/false,不能隐式转换为整数 - 字符类型:
char,Unicode 标量值,占 4 字节,用单引号
练习题
详见:练习题