数据类型

标量和复合类型

Rust是静态编译语言,在编译时必须知道所有变量的类型

基于使用的值,编译器通常能够推断出它的具体类型;

但如果可能的类型比较多(例如把String转为整数的parse方法),就必须添加类型的标注,否则编译会报错;

错误示例

fn main() {
    let res = "88".parse().expect("转换失败");
    println!("{}", res);
}

正确示例,标注类型

fn main() {
    let res:i16 = "88".parse().expect("转换失败");
    println!("{}", res);
}

Rust 的标量类型

整数类型(Integer Types)

i8:8 位有符号整数(signed 8-bit integer)。

i16:16 位有符号整数(signed 16-bit integer)。

i32:32 位有符号整数(signed 32-bit integer),这是最常用的整数类型,因为其在大多数平台上都有高效的实现。

i64:64 位有符号整数(signed 64-bit integer)。

i128:128 位有符号整数(signed 128-bit integer),在某些平台上可能不直接支持。

isize:指针大小的有符号整数(platform-dependent size),其大小与指针相同,通常用于索引和与操作系统交互。

u8:8 位无符号整数(unsigned 8-bit integer)。

u16:16 位无符号整数(unsigned 16-bit integer)。

u32:32 位无符号整数(unsigned 32-bit integer)。

u64:64 位无符号整数(unsigned 64-bit integer)。

u128:128 位无符号整数(unsigned 128-bit integer),在某些平台上可能不直接支持。

usize:指针大小的无符号整数(platform-dependent size),其大小与指针相同,通常用于索引和与操作系统交互。

浮点类型(Floating-Point Types)

f32:32 位单精度浮点数(single-precision floating-point number)。

f64:64 位双精度浮点数(double-precision floating-point number),这是最常用的浮点类型,因为它提供了足够的精度和性能。

浮点数陷阱

浮点数由于底层格式的特殊性,导致了如果在使用浮点数时不够谨慎,就可能造成危险,有两个原因:

1.浮点数往往是你想要数字的近似表达 浮点数类型是基于二进制实现的,但是我们想要计算的数字往往是基于十进制,例如 0.1 在二进制上并不存在精确的表达形式,但是在十进制上就存在。这种不匹配性导致一定的歧义性,更多的,虽然浮点数能代表真实的数值,但是由于底层格式问题,它往往受限于定长的浮点数精度,如果你想要表达完全精准的真实数字,只有使用无限精度的浮点数才行

2.浮点数在某些特性上是反直觉的 例如大家都会觉得浮点数可以进行比较,对吧?是的,它们确实可以使用 >,>= 等进行比较,但是在某些场景下,这种直觉上的比较特性反而会害了你。因为 f32 , f64 上的比较运算实现的是 std::cmp::PartialEq 特征(类似其他语言的接口),但是并没有实现 std::cmp::Eq 特征,但是后者在其它数值类型上都有定义,说了这么多,可能大家还是云里雾里,用一个例子来举例:

Rust 的 HashMap 数据结构,是一个 KV 类型的 Hash Map 实现,它对于 K 没有特定类型的限制,但是要求能用作 K 的类型必须实现了 std::cmp::Eq 特征,因此这意味着你无法使用浮点数作为 HashMap 的 Key,来存储键值对,但是作为对比,Rust 的整数类型、字符串类型、布尔类型都实现了该特征,因此可以作为 HashMap 的 Key。

为了避免上面说的两个陷阱,你需要遵守以下准则:

避免在浮点数上测试相等性
当结果在数学上可能存在未定义时,需要格外的小心

来看个小例子:

fn main() {
  // 断言0.1 + 0.2与0.3相等
  assert!(0.1 + 0.2 == 0.3);
}

你可能以为,这段代码没啥问题吧,实际上它会 panic(程序崩溃,抛出异常),因为二进制精度问题,导致了 0.1 + 0.2 并不严格等于 0.3,它们可能在小数点 N 位后存在误差。

那如果非要进行比较呢?可以考虑用这种方式 (0.1_f64 + 0.2 - 0.3).abs() < 0.00001 ,具体小于多少,取决于你对精度的需求。

fn main() {
    // 断言0.1 + 0.2与0.3相等
    assert!(0.1 + 0.2 - 0.3 < 0.0000001);
}

布尔类型(Boolean Type)

bool:布尔值,可以是 true 或 false。

字符类型(Character Type)

char:表示单个 Unicode 标量值(Unicode scalar value),通常用于处理单个字符。在 Rust 中,char 占用 4 个字节(32 位),以支持所有的 Unicode 字符。

符合类型

元组 Tuple

Tuple 可以将多个类型的多个值放在一个类型里,Tuple 的长度是固定的:一旦声明就无法改变。

使用 . 索引的方式访问元素。

一个声明、结构、调用的示例 :

fn main() {
    let tup:( i32, f64, u8) = (500, 6.4, 1);
    let (x, y, z) = tup;
    println!("The value of x is: {}", x);
    println!("The value of y is: {}", y);
    println!("The value of z is: {}", z);
    // 访问单个元素
    print!("The value of  is: {:?}", tup.0)
}

数组

数组也可以将多个值放在一个类型里,数组中每个元素的类型必须相同,数组的长度也是固定的。在Rust中会提供 Vector,Vector更加灵活(长度可变)。

示例 :

fn main() {
    let arr:[i32;5] = [1,2,3,4,5];
    println!("{:?}",arr);
    print!("{}",arr[0]);
}