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!() 的返回值也是单元类型 ()。

参考

相关推荐
yddddddy20 分钟前
css的基本知识
前端·css
昔人'22 分钟前
css `lh`单位
前端·css
Nan_Shu_6142 小时前
Web前端面试题(2)
前端
知识分享小能手2 小时前
React学习教程,从入门到精通,React 组件核心语法知识点详解(类组件体系)(19)
前端·javascript·vue.js·学习·react.js·react·anti-design-vue
蚂蚁RichLab前端团队3 小时前
🚀🚀🚀 RichLab - 花呗前端团队招贤纳士 - 【转岗/内推/社招】
前端·javascript·人工智能
孩子 你要相信光3 小时前
css之一个元素可以同时应用多个动画效果
前端·css
huangql5204 小时前
npm 发布流程——从创建组件到发布到 npm 仓库
前端·npm·node.js
咸甜适中4 小时前
rust语言 (1.88) egui (0.32.2) 学习笔记(逐行注释)(二十八)使用图片控件显示图片
笔记·学习·rust·egui
Days20504 小时前
LeaferJS好用的 Canvas 引擎
前端·开源
小白菜学前端4 小时前
vue2 常用内置指令总结
前端·vue.js