Rust 笔记(二)基本类型

Rust 是一门强调安全、并发、高效的系统编程语言。无 GC 实现内存安全机制、无数据竞争的并发机制、无运行时开销的抽象机制,是 Rust 独特的优越特性。 它声称解决了传统 C 语言和 C++语言几十年来饱受责难的内存安全问题,同时还保持了很高的运行效率、很深的底层控制、很广的应用范围, 在系统编程领域具有强劲的竞争力和广阔的应用前景。

接下来,为了快速入门 Rust,我们一起梳理 Rust 开发的基本内容。

Rust 每个值都有其确切的数据类型,总的来说可以分为两类:基本类型和复合类型。 基本类型意味着它们往往是一个最小化原子类型,无法解构为其它类型(一般意义上来说),由以下组成:

  • 数值类型: 有符号整数 (i8, i16, i32, i64, isize)、 无符号整数 (u8, u16, u32, u64, usize) 、浮点数 (f32, f64)、以及有理数、复数
  • 布尔类型: true和false
  • 字符类型: 表示单个 Unicode 字符,存储为 4 个字节
  • 单元类型: 即 () ,其唯一的值也是 ()

本文先带大家了解一下 Rust 的基本类型。

1. 数值类型

1.1 整数类型

整数类型分为有符号整数和无符号整数。 例如:i32 表示有符号的 32 位整数。 例如:u32 表示无符号的 32 位整数。 i 是英文单词 integer 的首字母,与之相反的是 u,代表无符号 unsigned 类型。

长度 有符合类型 无符合类型
8 位 i8 u8
16 位 i16 u16
32 位 i32 u32
64 位 i64 u64
128位 i128 u128
待定 isize usize

有符号则表示数字可以取正数、负数还有0。无符号数表示数字只能取正数和0。

每个有符号类型规定的数字范围是 -(2^(n 1)) ~ 2^(n - 1)-1其中 n 是该定义形式的位长度。因此 i8 可存储数字范围是 -(2^7)~~ 2^7-1,即 -128 ~ 127。

rust 复制代码
let _a: i8 = 127;

无符号类型可以存储的数字范围是 0 ~ 2^n- 1,所以 u8 能够存储的数字为 0 ~ 2^8- 1,即 0 ~ 255。

rust 复制代码
let _a: u8 = 255;

既然每一个类型都决定了数字的范围,那如果我们定义的数字超过了这个范围会怎么样了? 例如:

rust 复制代码
let _i: u8 = 256;
let _x: i8 = 128;

当在 debug 模式编译时,Rust 会检查整型溢出,若存在这些问题,则使程序在编译时崩溃。 当在 -- release 模式构建时,Rust 不检测溢出。当检测到整型溢出时,Rust 会按照补码循环溢出的规则处理。比如在 u8 的情况下,256 变成 0,257 变成 1。

此外,isize 和 usize 类型取决于程序运行的计算机 CPU 类型: 若 CPU 是 32 位的,则这两个类型是 32 位的,同理,若 CPU 是 64 位,那么它们则是 64 位。

我们知道 Rust 是一门静态类型语言,意思它会进行类型推导, Rust 整型默认使用 i32,例如:

rust 复制代码
 let _i = 1;

那 i 就是 i32 类型,这是 Rust 的默认类型推导。

1.2 浮点类型

在 Rust 中浮点类型数字也有两种基本类型: f32 和 f64,分别为 32 位和 64 位大小。默认浮点类型是 f64。

rust 复制代码
let x = 2.0; // f64
let y: f32 = 3.0; // f32

浮点数根据 IEEE-754 标准实现。f32 类型是单精度浮点型,f64 是双精度浮点型。

在 Rust 同样存在 0.1 + 0.2 === 0.3 的问题。

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

因为二进制精度问题,导致了 0.1 + 0.2 并不严格等于 0.3,它们可能在小数点 N 位后存在误差。 可以考虑用这种方式 (0.1_f64 + 0.2 - 0.3).abs() < 0.00001 ,来进行比较,这里的具体小于多少,取决于你对精度的需求。 对于 Rust 的浮点类型,问题还远远不止上面一个,比如还有:

rust 复制代码
fn main() {
    let abc: (f32, f32, f32) = (0.1, 0.2, 0.3);
    println!("   0.1 + 0.2: {:?}", (abc.0 + abc.1));
    println!("         0.3: {:?}", (abc.2));

    let xyz: (f64, f64, f64) = (0.1, 0.2, 0.3);
    println!("   0.1 + 0.2: {:?}", (xyz.0 + xyz.1));
    println!("         0.3: {:?}", (xyz.2));
}

在 f64 类型 01 + 0.2 = 0.30000000000000004,因为 f64 精度高很多,因此在小数点非常后面发生了一点微小的变化。 但是 32 下的 0.1 + 0.2 == 0.3 通过测试。 在 Rust 中也存在 NaN,对于未定义的结果那么 Rust 就会使用 NaN 来处理。 在 Rust 可以通过 is_nan 方法来判断一个数字是否是 NaN:

1.3 有理数和复数

对于前端同学来说,有理数和复数这两个类型可能没有听过。但是我想大家一定用过。

有理数是一个整数 a 和一个非零整数 b 的比,例如 3/8,通则为 a/b ,又称作分数。0也是有理数。有理数是整数和分数的集合,整数也可看做是分母为一的分数。有理数的小数部分是有限或为无限循环的数。不是有理数的实数称为无理数,即无理数的小数部分是无限不循环的数。而有理数和无理数统称为实数。

那么复数是指能写成如下形式的数 a+bi,这里 a 和 b 是实数,i 是虚数单位(即-1开根)。在复数 a + bi 中,a 称为复数的实部,b 称为复数的虚部,i 称为虚数单位。当虚部等于零时,这个复数就是实数;当虚部不等于零时,这个复数称为虚数。

在现阶段的 Rust 标准库中,还没有正式的包含的有理数和复数,但是在 Rust 社区中已经存在 Rust 数值库 num。这个库是 Rust 的数字类型和特征的集合,包括 bigint、complex、rational、范围迭代器、泛型整数等等!这里就不花过多的篇章来讲了。

2.字符类型

Rust 的字符不仅仅是 ASCII,所有的 Unicode 值都可以作为 Rust 字符,包括中文、日文、韩文、emoji 表情符号等等,都是合法的字符类型。Unicode 值的范围从 U+0000 ~ U+D7FF 和 U+E000 ~ U+10FFFF。不过"字符"并不是 Unicode 中的一个概念,所以人在直觉上对"字符"的理解和 Rust 的字符概念并不一致。

在 Rust 中字符只能用 '' 来表示, "" 是留给字符串的。 并且还需要注意区分的是字符的 char,而不是 &str。

rust 复制代码
let _a: char = 'b';
let _b: &str = "abc";

3.布尔类型

Rust 中的布尔类型和 JS 中一样有两个可能的值:true 和 false。

rust 复制代码
let _t: bool = true;
let _f: bool = false;

4.单元类型

单元类型就是 (),也叫做 unit。 Rust 函数参数的类型和返回值的类型都必须显式定义,如果没有返回值可以省略,返回 unit。函数内部如果提前返回,需要用 return 关键字,否则最后一个表达式就是其返回值。如果最后一个表达式后添加了; 分号,隐含其返回值为 unit。

main 函数就返回这个单元类型 (),println!() 的返回值也是单元类型 ()。

参考

相关推荐
cc蒲公英8 分钟前
vue2中使用vue-office库预览pdf /docx/excel文件
前端·vue.js
Sam902920 分钟前
【Webpack--013】SourceMap源码映射设置
前端·webpack·node.js
Python私教1 小时前
Go语言现代web开发15 Mutex 互斥锁
开发语言·前端·golang
A阳俊yi1 小时前
Vue(13)——router-link
前端·javascript·vue.js
小明说Java1 小时前
Vue3祖孙组件通信探秘:运用provide与inject实现跨层级数据传递
前端
好看资源平台1 小时前
前端框架对比与选择:如何在现代Web开发中做出最佳决策
前端·前端框架
4triumph1 小时前
Vue.js教程笔记
前端·vue.js
程序员大金2 小时前
基于SSM+Vue+MySQL的酒店管理系统
前端·vue.js·后端·mysql·spring·tomcat·mybatis
清灵xmf2 小时前
提前解锁 Vue 3.5 的新特性
前端·javascript·vue.js·vue3.5
白云~️2 小时前
监听html元素是否被删除,删除之后重新生成被删除的元素
前端·javascript·html