青少年编程与数学 02-019 Rust 编程基础 04课题、基本数据类型

发布于:2025-05-10 ⋅ 阅读:(18) ⋅ 点赞:(0)

青少年编程与数学 02-019 Rust 编程基础 04课题、基本数据类型

**摘要:**在 Rust 编程中,数据类型是构建程序的基础。基本数据类型是 Rust 中最核心的类型,它们是语言内置的,用于表示简单值。

**关键词:**数据类型、整数、浮点数、布尔值、字符、范围


一、整数类型

在 Rust 中,整数类型是编程中最常用的基本数据类型之一,用于表示整数值。Rust 提供了多种整数类型,以满足不同的需求,包括不同的大小(字节数)和是否有符号。以下是对 Rust 中整数类型的详细解析。

(一)整数类型的分类

Rust 中的整数类型分为两大类:有符号整数和无符号整数。

有符号整数

有符号整数可以表示正数、负数和零。Rust 提供了以下有符号整数类型:

类型 大小(字节) 范围(十进制)
i8 1 -128 到 127
i16 2 -32768 到 32767
i32 4 -2147483648 到 2147483647
i64 8 -9223372036854775808 到 9223372036854775807
i128 16 -17014118346046923182711181922996765564477470313856 到 17014118346046923182711181922996765564477470313855
isize 与平台相关 32 位系统:-2147483648 到 2147483647
64 位系统:-9223372036854775808 到 9223372036854775807

无符号整数

无符号整数只能表示非负整数(即零和正数)。Rust 提供了以下无符号整数类型:

类型 大小(字节) 范围(十进制)
u8 1 0 到 255
u16 2 0 到 65535
u32 4 0 到 4294967295
u64 8 0 到 18446744073709551615
u128 16 0 到 340282366920938463463374607431768211455
usize 与平台相关 32 位系统:0 到 4294967295
64 位系统:0 到 18446744073709551615

(二)整数类型的用途

整数类型在 Rust 中的用途非常广泛,以下是一些常见的使用场景:

变量初始化

let a: i32 = 42;
let b: u8 = 255;
let c: i64 = -9223372036854775808;

数学运算

整数类型支持常见的数学运算,如加法、减法、乘法、除法和取模。

let sum = 5 + 10; // 加法
let difference = 10 - 5; // 减法
let product = 4 * 30; // 乘法
let quotient = 56 / 7; // 除法
let remainder = 43 % 5; // 取模

数组索引

usize 类型常用于数组或向量的索引。

let array = [1, 2, 3, 4, 5];
let index: usize = 2;
println!("The value at index {} is {}", index, array[index]);

循环计数

在循环中,整数类型常用于计数。

for i in 0..5 {
    println!("i = {}", i);
}

(三)整数类型的特性

溢出行为

Rust 中的整数类型在溢出时的行为取决于编译模式:

  • 调试模式(Debug Mode):整数溢出会导致程序 panic(运行时错误)。
  • 发布模式(Release Mode):整数溢出会导致未定义行为(Undefined Behavior,UB)。为了避免溢出,可以使用 checked_addchecked_sub 等方法来安全地进行运算。
let a: u8 = 255;
let b: u8 = 1;

// 在调试模式下会导致 panic
// let c = a + b;

// 在发布模式下会导致未定义行为
// let c = a + b;

// 安全的加法
let c = a.checked_add(b);
if let Some(result) = c {
    println!("Result: {}", result);
} else {
    println!("Overflow occurred");
}

类型推断

Rust 编译器可以自动推断整数的类型,但在某些情况下,显式指定类型是必要的。如果未指定类型,整数字面量的默认类型是 i32

let a = 42; // 默认类型为 i32
let b: u32 = 42; // 显式指定类型为 u32

类型转换

Rust 提供了多种方式来转换整数类型,包括显式转换和自动强制转换。

  • 显式转换:使用 as 关键字进行类型转换。

    let a: i32 = 42;
    let b: u8 = a as u8; // 显式转换为 u8
    
  • 自动强制转换:在某些情况下,Rust 会自动将较小的整数类型转换为较大的整数类型。

    let a: i8 = 42;
    let b: i32 = a; // 自动强制转换为 i32
    

(四)整数类型的字面量

在 Rust 中,整数字面量可以有以下几种形式:

  • 十进制:直接写数字,如 42
  • 十六进制:以 0x 开头,如 0x2A(等同于十进制的 42)。
  • 八进制:以 0o 开头,如 0o52(等同于十进制的 42)。
  • 二进制:以 0b 开头,如 0b101010(等同于十进制的 42)。
  • 下划线分隔:可以在数字中使用下划线 _ 来分隔数字,提高可读性,如 1_000_000
let decimal = 42;
let hex = 0x2A;
let octal = 0o52;
let binary = 0b101010;
let large_number = 1_000_000;

(五)整数类型的溢出和饱和

Rust 提供了一些方法来处理整数溢出和饱和:

  • checked_add:如果加法会导致溢出,则返回 None
  • checked_sub:如果减法会导致溢出,则返回 None
  • checked_mul:如果乘法会导致溢出,则返回 None
  • checked_div:如果除法会导致溢出或除以零,则返回 None
  • saturating_add:如果加法会导致溢出,则返回类型的最大值或最小值。
  • saturating_sub:如果减法会导致溢出,则返回类型的最大值或最小值。
  • saturating_mul:如果乘法会导致溢出,则返回类型的最大值或最小值。
let a: u8 = 255;
let b: u8 = 1;

// 检查加法
let c = a.checked_add(b);
if let Some(result) = c {
    println!("Result: {}", result);
} else {
    println!("Overflow occurred");
}

// 饱和加法
let d = a.saturating_add(b);
println!("Saturating result: {}", d); // 输出 255

(六)整数类型的比较和布尔运算

整数类型支持常见的比较运算符(==!=><>=<=)和布尔运算符(&&||!)。

let a = 10;
let b = 20;

println!("a == b: {}", a == b); // false
println!("a != b: {}", a != b); // true
println!("a > b: {}", a > b); // false
println!("a < b: {}", a < b); // true
println!("a >= b: {}", a >= b); // false
println!("a <= b: {}", a <= b); // true

(七)整数类型的位运算

整数类型还支持位运算符,用于操作整数的二进制表示:

  • 按位与(&
  • 按位或(|
  • 按位异或(^
  • 按位取反(!
  • 左移(<<
  • 右移(>>
let a = 0b1101; // 二进制表示 13
let b = 0b1011; // 二进制表示 11

println!("a & b: {:04b}", a & b); // 1001
println!("a | b: {:04b}", a | b); // 1111
println!("a ^ b: {:04b}", a ^ b); // 0110
println!("!a: {:08b}", !a); // 11111010
println!("a << 2: {:04b}", a << 2); // 10100
println!("a >> 2: {:04b}", a >> 2); // 11

(八)整数类型的溢出检查

在 Rust 中,可以通过以下方式检查整数溢出:

  • 使用 checked_addchecked_subchecked_mul 等方法。
  • 使用 wrapping_addwrapping_subwrapping_mul 等方法,这些方法会在溢出时自动环绕。
let a: u8 = 255;
let b: u8 = 1;

// 检查加法
let c = a.checked_add(b);
if let Some(result) = c {
    println!("Result: {}", result);
} else {
    println!("Overflow occurred");
}

// 自动环绕加法
let d = a.wrapping_add(b);
println!("Wrapping result: {}", d); // 输出 0

(九)整数类型的特殊用途

isizeusize

  • isize:有符号整数,大小与目标平台的指针大小相同。通常用于表示可以为负的索引。
  • usize:无符号整数,大小与目标平台的指针大小相同。通常用于数组索引、内存分配等。
let index: isize = -1;
let size: usize = 10;

_ 占位符

在整数字面量中,可以使用 _ 作为占位符,以提高可读性。_ 不会影响值的实际大小。

let large_number = 1_000_000_000;
println!("Large number: {}", large_number); // 输出 1000000000

整数类型总结

Rust 的整数类型提供了丰富的功能和灵活性,以满足不同的编程需求。通过理解整数类型的大小、范围、溢出行为以及类型转换规则,可以更安全、高效地使用整数类型。同时,Rust 提供的溢出检查和位运算功能也为开发者提供了强大的工具,用于处理复杂的数值操作。

二、浮点数类型

在 Rust 中,浮点数类型用于表示小数和实数。与整数类型不同,浮点数类型可以表示分数、小数以及非常大或非常小的数值。Rust 提供了两种主要的浮点数类型:f32f64。它们都遵循 IEEE 754 标准,分别对应单精度和双精度浮点数。

(一)浮点数类型的分类

f32

  • 大小:32 位(4 字节)
  • 精度:大约 7 位十进制数字
  • 范围:大约 ±1.2×10⁻³⁸ 到 ±3.4×10³⁸
  • 用途:适用于对精度要求不高,但需要节省内存的场景,例如图形处理和科学计算中的轻量级应用。

f64

  • 大小:64 位(8 字节)
  • 精度:大约 15 位十进制数字
  • 范围:大约 ±2.2×10⁻³⁰⁸ 到 ±1.8×10³⁰⁸
  • 用途:适用于需要更高精度的场景,例如金融计算、高精度的科学计算等。

(二)浮点数字面量

浮点数字面量可以直接在代码中表示浮点数。Rust 中的浮点数字面量有以下几种形式:

十进制表示

直接写数字和小数点:

let pi = 3.141592653589793;
let e = 2.718281828459045;

科学计数法

使用 eE 表示指数部分:

let large_number = 1.23e4; // 等同于 12300.0
let small_number = 1.23e-4; // 等同于 0.000123

类型后缀

可以显式指定类型后缀,以明确表示浮点数的类型:

let pi_f32: f32 = 3.141592653589793f32;
let e_f64: f64 = 2.718281828459045f64;

(三)浮点数的特性

精度问题

浮点数的精度是有限的,因此在进行浮点数运算时可能会出现精度误差。例如:

let a = 0.1 + 0.2;
println!("{}", a); // 输出 0.30000000000000004

这种现象是由于浮点数的二进制表示方式导致的,无法完全精确地表示某些十进制小数。

特殊值

浮点数类型还支持一些特殊值:

  • 正无穷(f32::INFINITYf64::INFINITY
  • 负无穷(f32::NEG_INFINITYf64::NEG_INFINITY
  • 非数字(NaN,f32::NANf64::NAN
let positive_infinity = f32::INFINITY;
let negative_infinity = f32::NEG_INFINITY;
let not_a_number = f32::NAN;

println!("{}", positive_infinity); // 输出 inf
println!("{}", negative_infinity); // 输出 -inf
println!("{}", not_a_number); // 输出 nan

比较浮点数

由于浮点数的精度问题,直接比较两个浮点数是否相等可能会导致意外的结果。因此,通常使用一个“容忍度”(epsilon)来进行比较:

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

let a = 0.1 + 0.2;
let b = 0.3;
println!("{}", float_equal(a, b, 1e-10)); // 输出 true

(四)浮点数的操作

基本运算

浮点数支持常见的数学运算,包括加法、减法、乘法、除法等:

let sum = 1.0 + 2.0;
let difference = 5.0 - 3.0;
let product = 4.0 * 3.0;
let quotient = 10.0 / 2.0;

数学函数

Rust 的标准库提供了丰富的数学函数,用于处理浮点数,例如:

  • abs:绝对值
  • sqrt:平方根
  • sincostan:三角函数
  • exp:指数函数
  • ln:自然对数
use std::f64::consts::PI;

let x = 3.14;
println!("Absolute value: {}", x.abs()); // 输出 3.14
println!("Square root: {}", x.sqrt()); // 输出 1.772004514666935
println!("Sine: {}", (PI / 2.0).sin()); // 输出 1.0
println!("Exponential: {}", x.exp()); // 输出 23.10386685872218
println!("Natural logarithm: {}", x.ln()); // 输出 1.1447298858494002

类型转换

可以使用 as 关键字将浮点数转换为其他类型,例如:

let x: f64 = 3.14;
let y: i32 = x as i32; // 转换为整数,截断小数部分
println!("{}", y); // 输出 3

(五)浮点数的限制

精度限制

浮点数的精度是有限的,因此不适合用于精确的金融计算。对于需要高精度的场景,建议使用整数或专门的库(如 rust_decimal)来处理。

NaN 的特殊行为

NaN(非数字)值在比较和运算中具有特殊行为:

  • NaN 与任何值(包括自身)的比较都返回 false
  • NaN 与任何值的运算结果仍然是 NaN。
let nan = f32::NAN;
println!("{}", nan == nan); // 输出 false
println!("{}", nan + 1.0); // 输出 nan

(六)使用场景

  • 科学计算:f64 由于其高精度,常用于科学计算、物理模拟等场景。
  • 图形处理:f32 由于其较小的内存占用,常用于图形处理和实时渲染。
  • 金融计算:虽然浮点数不适合精确的金融计算,但在某些近似计算中仍然可以使用。

浮点数类型总结

Rust 中的浮点数类型 f32f64 提供了强大的功能,用于表示和处理小数和实数。它们遵循 IEEE 754 标准,支持丰富的数学运算和函数。然而,由于浮点数的精度限制,使用时需要注意精度问题和特殊值的行为。通过合理选择浮点数类型并正确处理精度问题,可以有效地利用浮点数在各种计算场景中。

三、字符类型

在 Rust 中,字符类型(char)用于表示单个 Unicode 标量值。它是 Rust 提供的基本数据类型之一,用于处理文本数据中的单个字符。与一些其他语言(如 C 或 C++)中的字符类型不同,Rust 的 char 类型是 Unicode-aware 的,这意味着它可以表示任何 Unicode 字符,而不仅仅是 ASCII 字符。

(一)char 类型的特点

Unicode 支持

Rust 的 char 类型是基于 Unicode 标准设计的,每个 char 类型的变量占用 4 个字节(32 位),可以表示任何 Unicode 标量值。这包括常见的字母、数字、标点符号,以及各种语言的字符、表情符号等。

let letter: char = 'a';       // 英文字母
let digit: char = '9';        // 数字字符
let chinese_char: char = '中'; // 中文字符
let emoji: char = '😊';       // 表情符号

1.2 固定大小

char 类型的大小是固定的,始终为 4 个字节。这与某些语言(如 C 或 C++)中的 char 类型不同,后者的大小通常为 1 个字节,并且只能表示 ASCII 字符。

不是字节

Rust 的 char 类型并不是字节类型。如果需要处理字节数据,应该使用 u8 类型。char 类型用于表示 Unicode 字符,而 u8 类型用于表示字节。

(二)字符字面量

在 Rust 中,字符字面量用单引号 ' 包裹。字符字面量可以包含以下内容:

2.1 普通字符

可以直接写入单个字符:

let letter: char = 'a';
let digit: char = '9';
let punctuation: char = '!';

Unicode 字符

可以使用 Unicode 转义序列 \u{} 来表示 Unicode 字符。转义序列中的 {} 内是一个十六进制数,表示 Unicode 码点:

let chinese_char: char = '\u{4E2D}'; // 中
let emoji: char = '\u{1F600}';      // 😀

转义字符

可以使用转义字符来表示一些特殊字符,例如:

  • \n:换行符
  • \t:制表符
  • \\:反斜杠
  • \':单引号
  • \":双引号
let newline: char = '\n';
let tab: char = '\t';
let backslash: char = '\\';
let single_quote: char = '\'';
let double_quote: char = '\"';

(三)字符类型的操作

字符比较

字符类型支持比较运算符(==!=><>=<=),用于比较两个字符的 Unicode 码点值。

let a: char = 'a';
let b: char = 'b';

println!("a == b: {}", a == b); // false
println!("a < b: {}", a < b);   // true
println!("a > b: {}", a > b);   // false

字符转换

可以将字符转换为对应的 Unicode 码点值(u32 类型),也可以从 Unicode 码点值转换回字符。

let c: char = 'a';
let code_point: u32 = c as u32; // 转换为 Unicode 码点值
println!("The Unicode code point of 'a' is {}", code_point); // 输出 97

let d: char = std::char::from_u32(97).unwrap(); // 从 Unicode 码点值转换回字符
println!("The character for Unicode code point 97 is {}", d); // 输出 'a'

字符迭代

可以使用 chars() 方法来迭代字符串中的字符。

let text = "Hello, 世界!";
for c in text.chars() {
    println!("{}", c);
}

(四)字符类型的限制

不支持多字节字符直接表示

虽然 Rust 的字符串(String&str)支持多字节的 UTF-8 编码,但 char 类型只能表示单个 Unicode 标量值。如果需要处理多字节的文本数据,应该使用字符串类型。

无效的 Unicode 码点

在从 u32 转换为 char 时,必须确保提供的码点是有效的 Unicode 码点。如果码点无效,std::char::from_u32 方法会返回 None

let invalid_code_point: u32 = 0xD800; // 无效的 Unicode 码点
let invalid_char = std::char::from_u32(invalid_code_point);
println!("{:?}", invalid_char); // 输出 None

(五)使用场景

5.1 单个字符处理

当需要处理单个字符时,char 类型非常方便。例如,处理用户输入的单个字符、解析文本文件中的字符等。

fn is_vowel(c: char) -> bool {
    match c {
        'a' | 'e' | 'i' | 'o' | 'u' => true,
        _ => false,
    }
}

let input = 'e';
println!("Is '{}' a vowel? {}", input, is_vowel(input)); // 输出 true

Unicode 字符处理

由于 char 类型支持 Unicode,它可以用于处理多种语言的字符,包括中文、日文、阿拉伯文等。

let chinese_text = "你好,世界!";
for c in chinese_text.chars() {
    println!("{}", c);
}

字符类型总结

Rust 的 char 类型是一个功能强大的基本数据类型,用于表示单个 Unicode 标量值。它支持 Unicode,占用 4 个字节,可以表示任何 Unicode 字符。通过使用字符字面量、比较操作、转换操作和迭代操作,可以方便地处理字符数据。然而,需要注意的是,char 类型并不适合处理多字节的文本数据,这种情况下应该使用字符串类型(String&str)。

四、布尔类型

在 Rust 中,布尔类型(bool)用于表示逻辑值,是编程中处理条件和逻辑判断的基础。布尔类型在 Rust 中非常简单,但它在控制程序流程和逻辑判断中起着关键作用。以下是对 Rust 中布尔类型的详细解析。

(一)布尔类型的定义

布尔类型在 Rust 中只有一个关键字:bool。它只有两个可能的值:

  • true:表示逻辑上的“真”。
  • false:表示逻辑上的“假”。

(二)布尔类型的大小

布尔类型在 Rust 中占用 1 个字节(8 位)。虽然它只有两个值,但它的大小是固定的,这使得它在内存中具有明确的布局。

(三)布尔类型的用途

布尔类型主要用于条件判断和逻辑运算。以下是一些常见的使用场景:

条件判断

布尔类型常用于 ifwhileloop 等控制流语句中,用于决定程序的执行路径。

let is_active: bool = true;

if is_active {
    println!("The user is active.");
} else {
    println!("The user is not active.");
}

逻辑运算

布尔类型支持逻辑运算符,用于组合多个布尔表达式:

  • 逻辑与(&&):当两个操作数都为 true 时,结果为 true
  • 逻辑或(||):当两个操作数中至少有一个为 true 时,结果为 true
  • 逻辑非(!):对布尔值取反。
let is_active: bool = true;
let is_admin: bool = false;

if is_active && is_admin {
    println!("The user is active and an admin.");
} else if is_active || is_admin {
    println!("The user is either active or an admin.");
} else {
    println!("The user is neither active nor an admin.");
}

if !is_active {
    println!("The user is not active.");
}

(四)布尔类型的字面量

布尔类型的字面量只有两个:

  • true
  • false

它们可以直接在代码中使用,无需任何前缀或后缀。

(五)布尔类型的隐式转换

在 Rust 中,布尔类型不会隐式转换为其他类型(如整数或浮点数)。布尔值只能用于布尔上下文(如条件判断)。如果需要将布尔值转换为其他类型,必须显式进行转换。

let is_active: bool = true;
let active_as_i32: i32 = if is_active { 1 } else { 0 };
println!("Active as i32: {}", active_as_i32);

(六)布尔类型的特殊用途

在模式匹配中

布尔类型也可以用于模式匹配中,尤其是在 match 表达式中。

fn check_status(is_active: bool) {
    match is_active {
        true => println!("The user is active."),
        false => println!("The user is not active."),
    }
}

fn main() {
    check_status(true);
    check_status(false);
}

6.2 在函数返回值中

布尔类型常用于函数的返回值,表示操作的成功与否。

fn is_even(number: i32) -> bool {
    number % 2 == 0
}

fn main() {
    let number = 42;
    if is_even(number) {
        println!("{} is even.", number);
    } else {
        println!("{} is odd.", number);
    }
}

(七)布尔类型的限制

不能隐式转换

布尔类型不能隐式转换为其他类型,也不能从其他类型隐式转换为布尔类型。例如,不能将非零整数直接用作布尔值。

let number: i32 = 42;
// let is_non_zero: bool = number; // 错误:不能隐式转换
let is_non_zero: bool = number != 0; // 正确:显式比较

不能直接参与算术运算

布尔类型不能直接参与算术运算。如果需要将布尔值用于算术运算,必须先将其显式转换为数值类型。

let is_active: bool = true;
// let result = is_active + 1; // 错误:不能直接参与算术运算
let result = if is_active { 1 } else { 0 } + 1; // 正确:显式转换

布尔类型总结

Rust 的布尔类型 bool 是一个简单而强大的类型,用于表示逻辑值。它只有两个可能的值:truefalse,并且占用 1 个字节。布尔类型主要用于条件判断和逻辑运算,支持逻辑与、逻辑或和逻辑非运算符。通过合理使用布尔类型,可以有效地控制程序的流程和逻辑。

五、范围类型

在 Rust 中,范围类型(Range Types)并不是传统意义上的“基本数据类型”,但它们是 Rust 提供的一种非常有用的语法结构,用于表示一系列连续的值。范围类型在循环、迭代器以及数组切片等场景中非常常见。

(一)范围类型的分类

Rust 提供了几种范围类型,每种类型都有不同的用途和语义:

包含范围(std::ops::RangeInclusive

表示一个包含起始值和结束值的范围,即 [start, end]

  • 语法:start..=end
  • 特点:包含起始值和结束值。

排他范围(std::ops::Range

表示一个包含起始值但不包含结束值的范围,即 [start, end)

  • 语法:start..end
  • 特点:包含起始值,但不包含结束值。

开始范围(std::ops::RangeFrom

表示从某个值开始到无穷大的范围,即 [start, ∞)

  • 语法:start..
  • 特点:没有明确的结束值。

结束范围(std::ops::RangeTo

表示从零开始到某个值的范围,即 [0, end)

  • 语法:..end
  • 特点:起始值默认为零。

全范围(std::ops::RangeFull

表示从零开始到无穷大的范围,即 [0, ∞)

  • 语法:..
  • 特点:没有明确的起始值和结束值。

(二)范围类型的用途

范围类型在 Rust 中的用途非常广泛,以下是一些常见的使用场景:

for 循环中

范围类型常用于 for 循环中,用于迭代一系列值。

// 包含范围
for i in 1..=5 {
    println!("{}", i); // 输出 1 到 5
}

// 排他范围
for i in 1..5 {
    println!("{}", i); // 输出 1 到 4
}

// 开始范围
for i in 5.. {
    println!("{}", i); // 从 5 开始,无限循环
    if i > 10 {
        break;
    }
}

// 结束范围
for i in ..5 {
    println!("{}", i); // 输出 0 到 4
}

// 全范围
for i in .. {
    println!("{}", i); // 从 0 开始,无限循环
    if i > 10 {
        break;
    }
}

在数组切片中

范围类型也常用于数组或向量的切片操作中。

let array = [1, 2, 3, 4, 5];

// 使用排他范围
let slice1 = &array[1..3]; // [2, 3]
println!("{:?}", slice1);

// 使用包含范围
let slice2 = &array[1..=3]; // [2, 3, 4]
println!("{:?}", slice2);

// 使用开始范围
let slice3 = &array[3..]; // [4, 5]
println!("{:?}", slice3);

// 使用结束范围
let slice4 = &array[..3]; // [1, 2, 3]
println!("{:?}", slice4);

// 使用全范围
let slice5 = &array[..]; // [1, 2, 3, 4, 5]
println!("{:?}", slice5);

在模式匹配中

范围类型也可以用于模式匹配中,尤其是在匹配字符或整数时。

fn match_range(x: i32) {
    match x {
        1..=5 => println!("1 to 5"),
        6..=10 => println!("6 to 10"),
        _ => println!("Other"),
    }
}

fn main() {
    match_range(3); // 输出 "1 to 5"
    match_range(8); // 输出 "6 to 10"
    match_range(15); // 输出 "Other"
}

(三)范围类型的实现细节

范围类型实际上是 Rust 标准库中定义的结构体,它们实现了 Iterator 和其他相关的 trait,使得范围类型可以用于迭代和切片操作。

  • std::ops::Rangestruct Range<Idx> { start: Idx, end: Idx }
  • std::ops::RangeInclusivestruct RangeInclusive<Idx> { start: Idx, end: Idx }
  • std::ops::RangeFromstruct RangeFrom<Idx> { start: Idx }
  • std::ops::RangeTostruct RangeTo<Idx> { end: Idx }
  • std::ops::RangeFullstruct RangeFull {}

(四)范围类型的限制

  • 范围类型只能用于可比较的类型(如整数、字符等),不能用于浮点数类型(f32f64),因为浮点数的比较可能会涉及精度问题。
  • 范围的起始值必须小于或等于结束值,否则会导致空范围。

范围类型总结

Rust 的范围类型提供了一种非常灵活的方式来表示一系列连续的值。它们在循环、数组切片和模式匹配等场景中非常有用。通过合理使用范围类型,可以使代码更加简洁和高效。

六、综合示例

以下是一个综合示例代码,展示了 Rust 中各种基本数据类型的使用,包括整数、浮点数、字符、布尔值和范围类型:

fn main() {
    // 整数类型
    let a: i8 = 127;
    let b: u8 = 255;
    let c: i32 = -2147483648;
    let d: u32 = 4294967295;
    let e: i64 = -9223372036854775808;
    let f: u64 = 18446744073709551615;
    let g: isize = 10; // 与平台相关
    let h: usize = 20; // 与平台相关

    println!("整数类型:");
    println!("a (i8): {}", a);
    println!("b (u8): {}", b);
    println!("c (i32): {}", c);
    println!("d (u32): {}", d);
    println!("e (i64): {}", e);
    println!("f (u64): {}", f);
    println!("g (isize): {}", g);
    println!("h (usize): {}", h);

    // 浮点数类型
    let pi: f32 = std::f32::consts::PI; 
    let e: f64 = std::f64::consts::E; 

    println!("\n浮点数类型:");
    println!("pi (f32): {}", pi);
    println!("e (f64): {}", e);

    // 字符类型
    let letter: char = 'a';
    let digit: char = '9';
    let chinese_char: char = '中';
    let emoji: char = '😊';

    println!("\n字符类型:");
    println!("letter: {}", letter);
    println!("digit: {}", digit);
    println!("chinese_char: {}", chinese_char);
    println!("emoji: {}", emoji);

    // 布尔类型
    let is_active: bool = true;
    let is_admin: bool = false;

    println!("\n布尔类型:");
    println!("is_active: {}", is_active);
    println!("is_admin: {}", is_admin);

    // 范围类型
    println!("\n范围类型:");
    println!("包含范围 (1..=5):");
    for i in 1..=5 {
        println!("{}", i);
    }

    println!("排他范围 (1..5):");
    for i in 1..5 {
        println!("{}", i);
    }

    println!("开始范围 (5..):");
    for i in 5..11 { // 明确指定结束条件,避免无限循环
        println!("{}", i);
    }

    println!("结束范围 (..5):");
    for i in 0..5 { // 明确指定起始值
        println!("{}", i);
    }

    println!("全范围 (..):");
    for i in 0..11 { // 明确指定起始和结束值,避免无限循环
        println!("{}", i);
    }

    // 综合示例:计算一个整数的平方根并判断是否为正数
    let number: i32 = 16;
    let sqrt_number: f64 = (number as f64).sqrt();

    println!("\n综合示例:");
    println!("number: {}", number);
    println!("sqrt_number: {}", sqrt_number);
    if sqrt_number > 0.0 {
        println!("sqrt_number is positive.");
    } else {
        println!("sqrt_number is not positive.");
    }
}

运行结果

整数类型:
a (i8): 127
b (u8): 255
c (i32): -2147483648
d (u32): 4294967295
e (i64): -9223372036854775808
f (u64): 18446744073709551615
g (isize): 10
浮点数类型:20
pi (f32): 3.1415927
字符类型:2.718281828459045
letter: a
digit: 9
chinese_char: 中
布尔类型:
is_active: true
is_admin: false

范围类型:
包含范围 (1..=5):
1
2
3
4
5
排他范围 (1..5):
1
2
3
4
开始范围 (5..):
5
6
7
8
9
10
结束范围 (..5):
0
1
2
3
4
全范围 (..):
0
1
2
3
4
5
6
7
8
9
10

综合示例:
number: 16
sqrt_number: 4
sqrt_number is positive.

代码说明

  1. 整数类型

    • 定义了多种整数类型(有符号和无符号)的变量,并打印它们的值。
    • 展示了不同大小的整数类型以及 isizeusize 的使用。
  2. 浮点数类型

    • 定义了 f32f64 类型的变量,并打印它们的值。
  3. 字符类型

    • 定义了普通字符、数字字符、中文字符和表情符号,并打印它们的值。
  4. 布尔类型

    • 定义了布尔变量,并打印它们的值。
  5. 范围类型

    • 展示了包含范围、排他范围、开始范围、结束范围和全范围的使用,并在 for 循环中打印范围内的值。
  6. 综合示例

    • 计算一个整数的平方根,并判断结果是否为正数,展示了浮点数运算和布尔逻辑的结合。

运行此代码将展示 Rust 中各种基本数据类型的使用方法。

基本数据类型总结

Rust 的 基本数据类型 包括:

  1. 整数类型:i8u8i16u16i32u32i64u64i128u128isizeusize
  2. 浮点数类型:f32f64
  3. 字符类型:char
  4. 布尔类型:bool
  5. 范围类型:[start, end]

这些基本数据类型是 Rust 编程的基础,它们提供了简单而高效的值表示方式。


网站公告

今日签到

点亮在社区的每一天
去签到