学Rust,进华为!学习Rust中的基本数据类型和复合数据类型

查理谈科技 2024-05-12 22:54:05

学Rust, 进华为! 了解Rust 语言的基本数据类型和复合数据类型。

华为支持Rust语言,并在内部有很多项目使用Rust进行开发。华为还将Rust作为其可信计算的编程语言。

此外, 由华为开源并无偿捐赠给开放原子开源基金会的OpenHarmony项目,现在已经实现了与Rust 的互相支持,并使用Rust 重写了上传、下载等模块, 性能有明显的提升。

要想进入华为工作,熟练掌握Rust语言是一个进入华为工作的理想途径, 趁大家还不是很懂Rust, 赶紧学起来吧!

本文将开始学习Rust中的数据类型以及函数的用法。

创建项目

首先, 来创建一个新的Rust 项目:

cargo new datatype_function

执行结果:

learn_rust % cargo new datatype_functionCreated binary (application) `datatype_function` packagelearn_rust % cd datatype_function

Rust中的数据类型

Rust作为一个强类型语言,在Rust中的每一个对象的值都会有一个确定的数据类型;在这里将介绍Rust 的两种数据子类型: 标量(scala)和复合(compound)。

标量(Scala) 表示Rust对象有单个值。 Rust 中,有四种Scala 类型:

整数(integer)浮点数(float)布尔值(bool,true|false)字符(char)Rust 的整数类型

长度

有符号

无符号

8 bit

i8

u8

16 bit

i16

u16

32 bit

i32

i32

64 bit

i64

u64

128 bit

i128

u128

同C++/Java等语言一样, 每个数字类型变量可以区分为有符号和无符号两种, 有符号数字可以存储小于0的负数;每个整数类型可以存储的数字范围, 对于有符号整数而言是-2^(n-1) ~ 2^(n-1)-1, 因此 i8可以存储的数字范围是 -2^7 ~ 2^7-1, 也就是-128 ~ 127, 而u8 的范围则是0 ~ 127.

值得注意⚠️的是,对于整数的书写, Rust 中既允许数字的最后添加表示数字类型的后缀, 例如42u8; 同时也可以在数字中间加上下划线‘_’, 例如20_24; 还可以在数字的前面增加表示八进制、十六进制等的前缀, 例如0xfe表示十六进制数字(Hex); 0o77 表示八进制(Octal),0b1111_0000表示二进制数字。

考考你, 下面x1~ x4, 哪个数字大?

fn main() { //比一比,哪个数字大? let x1 = 2_54; let x2 = 0xfe; let x3 = 0o377; let x4 = 0b1111_1110; println!("Hello, x1={x1},x2={x2},x3={x3},x4={x4}");}

看看结果, 你猜对了吗?

/Users/Think/.cargo/bin/cargo run --color=always --package datatype_function --bin datatype_functionFinished dev [unoptimized + debuginfo] target(s) in 0.00sRunning `target/debug/datatype_function`Hello, x1=254,x2=254,x3=255,x4=254Rust 的浮点类型

Rust的浮点类型数字符合IEEE-754 标准, f32表示单精度浮点数, f64表示双精度浮点数,默认的类型为f64;Rust中具体的浮点数怎么存储, 在这里我们不再深入理解。

IEEE 754

例如下面的代码中, f1 貌似没有给出数据类型:

//浮点数let f1 = 2.0;//f64let f2 :f32 = 3.1;//f32println!("f1={},f2={}",f1,f2);

但实际上, 在IDE中f1是有默认的数字类型f64的,注意看第13行的f64, 灰色的字体f64表示是默认添加的:

Rust 中的数字运算: 加减乘除、求余

Rust中的数字运算,有五个操作符: +,-,*,/,%, 分别表示加减乘除、求余。

看代码理解:

// 加法 let sum = 0.1 + 0.2; // 减法 let sub = 95.5 - 4.3; // 乘法 let mul = 4 * 30; // 除法 let div = 129.6 / 32.4; // 求余 let rem = 43 % 5; println!("sum ={sum}, sub={sub},mul={mul},div={div},rem={rem}");

这些数字的运算看起来十分简单, 实际不然,先来看结果:

为什么0.1+ 0.2 不等于0.3? 这其实就是大名鼎鼎的浮点数运算的精度问题, 这个不能怪Rust, 这其实涉及计算机中对于数字精度的存储不够。

在维基百科中,是这么记载这个精度问题的:

浮点数无法准确表示所有实数,并且浮点运算无法准确表示真正的算术运算,这一事实导致了许多令人惊讶的情况。 这与计算机通常表示数字的有限精度有关。

例如,十进制数 0.1 和 0.01 无法精确表示为二进制浮点数。 在具有 24 位有效数的 IEEE 754 二进制 32 格式中,尝试将近似值平方为 0.1 的结果既不是 0.01,也不是最接近它的可表示数字。 十进制数 0.1 用二进制表示为 e = −4; s = 110011001100110011001101,即

正好是0.100000001490116119384765625。

将此数字平方得出

0.010000000298023226097399174250313080847263336181640625 正好。

将其平方并四舍五入到 24 位精度得出

正好是0.010000000707805156707763671875。

但最接近 0.01 的可表示数字是

准确地说是0.009999999776482582092285156250。

这个就与Rust 无关, 而是完全与硬件相关,因为根本无法用 32 或 64 位很好地表示实数。

那么在Rust中,想做一些精度高的浮点数运算, 该怎么办呢?

Rust 没有内置的decimal类型。 然而,有各种实现decimal类型的包,例如 rust_decimal。 rust_decimal 箱实现了由关键字 Decimal 表示的 128 位有限精度十进制类型,例如可以使用下面的代码来进行计算:

use rust_decimal::prelude::*;let a = Decimal::new(1, 1); // second param is the number of fractional digitslet b = Decimal::new(2, 1); // a Decimal representing exactly 0.2let c = a + b; // a Decimal representing exactly 0.3

Rust中的布尔类型

Rust中的布尔类型用bool表示, 只有两个值: true 和false; bool 类型还可以用在if等控制语句中:

let f = false; println!("f={f}"); if f { println!("f is true"); }else{ println!("f is false"); }

Rust中的字符类型(char)

Rust中, 字符类型char 使用单引号,表示一个字符;而字符串使用双引号。

值得注意⚠️的是, Rust的char类型使用4个字节,因此不仅仅包括了常用的ASCII字符集, 还可以表示汉字、emoji表情符号等。

//char 类型let c = 'c';let z: char = '汉'; // with explicit type annotationlet m = '';println!("c={c},z={z},m={m}");

执行结果:

c=c,z=汉,m=

Rust的复合数据类型(compound)

所谓复合类型(Compound type), 指的是一个类型包含多个值, 在Rust中有两种复合类型: 元组(tuple)和数组(array)。

Rust的元组(tuple )

元组指的是,在一个数据类型中,包含了多个数值, 这些数值又会有不同的数据类型。元组一旦定义,长度就是固定的, 之后不可以增加或者减少。

语言总是太过于抽象, 还是来一个例子:

//tuple 例子let tupl:(i32, f64,u32) = (500,3.14, 128);

在这个例子里, tupl对象包含三个数字, 每个元组的类型都需要在变量后面的括号中定义。通过这种方式, 可以一次性给多个变量赋值。

下面来看怎么获取元组中的值:

//tuple 例子let tupl:(i32, f64,u32) = (500,3.14, 128);println!("元组tupl包含的值是{:?}",tupl);//获取tuple的元素let (t1,t2,t3) = tupl;println!("t1值是{t1},t2是{t2},t3是{t3}");//逐个获取元组的元素println!("元组tupl中第一个值是{},第二个值是{},第三个值是{}",tupl.0, tupl.1, tupl.2);

上面的代码中,包含了使用{:?}打印tuple的值,以及把 tuple的值赋值给单个变量, 或者使用下标(从0开始)逐个读取tuple的值。

运行结果:

元组tupl包含的值是(500, 3.14, 128)

t1值是500,t2是3.14,t3是128

元组tupl中第一个值是500,第二个值是3.14,第三个值是128

默认地,元组(tuple)对象的内容是不可修改的, 也就是声明之后, 元素的内容不可修改; 如果想要修改的话,就要加上mut 关键字:

// 创建一个 mutable tuplelet mut top_three_mountains = ("珠穆朗玛峰", 8848, "乔峰", 184,"干城章嘉峰",8586);println!("世界前三高的山峰:{:?}",top_three_mountains);//下面修改第二高的山峰名称和高度top_three_mountains.2="乔戈里峰";top_three_mountains.3=8611;println!("确认无误的世界前三高的山峰:{:?}",top_three_mountains);

上面的例子里,首先在创建的tuple 变量top_three_mountains 前面,增加了一个mut 关键字,表示变量top_three_mountains 的值可以修改。然后就修改了第二高的山峰名称以及高度, 看下面的结果:

世界前三高的山峰:("珠穆朗玛峰", 8848, "乔峰", 184, "干城章嘉峰", 8586)

确认无误的世界前三高的山峰:("珠穆朗玛峰", 8848, "乔戈里峰", 8611, "干城章嘉峰", 8586)

下面来学习Rust 中的数组(array)

Rust的数组(array )

同元组相比,元组可以包含多种不同类型的元素, 数组(array)就是包含同类型元素的复合类型,array中的数据类型必须是相同的。

例如:

let natrual_number_array: [i32; 5] = [1, 2, 3, 4, 5]; println!("数组内容:{:?}",natrual_number_array); println!("数组的第一个元素:{}",natrual_number_array[0]);

当然,上面的例子是有些简单, 下面来看看数组元素的迭代访问

Rust中的数组迭代

注意⚠️, 在Rust中, 元素是不可以迭代访问的, 数组可以,方法看代码:

//数组迭代let prime_number = [2,3,5,7,11,13,17,19];for prime in prime_number { println!("当前素数是:{prime}");}

运行结果:

数组内容:[1, 2, 3, 4, 5]

数组的第一个元素:1

当前素数是:2

当前素数是:3

当前素数是:5

当前素数是:7

当前素数是:11

当前素数是:13

当前素数是:17

当前素数是:19

回顾

本文讲解了Rust 中的五大基本元素, 以及两个复合类型元素tuple 和array, 以及每种类型变量的读取方法。

当然, Rust中的数据类型是很丰富的,本文介绍的这些数据类型都是以栈(Stack)为基础的数据类型,所以连基本的String 类型都没有介绍:

不过没关系, Rust 本身也是很复杂的,让我们慢慢学习,不断进步吧!

本文代码已经提交到github,地址:https://github.com/hintcnuie/learn_rust



0 阅读:1

查理谈科技

简介:感谢大家的关注