Rust初见

基本类型

数值类型

整型溢出

u8举例,可以存放0-255。在debug模式下,编译器会检查整型溢出,例如存放了256,编译时会产生panic
当使用--release参数时,Rust反而又不检查溢出,而是按照补码循环溢出处理。例如256会变成0,257会变成1,以此类推。但终究不是想要的值,所以感觉没有卵用
可以通过以下方式显式处理原始数字类型可能的溢出。

  • 使用 wrapping_* 方法在所有模式下都按照补码循环溢出规则处理,例如 wrapping_add
  • 如果使用 checked_* 方法时发生溢出,则返回 None 值
  • 使用 overflowing_* 方法返回该值和一个指示是否存在溢出的布尔值
  • 使用 saturating_* 方法使值达到最小值或最大值
fn main() {
    let a = 255u8;
    let b = a.wrapping_add(1);
    println!("{}",b)
}
//输出结果为0

浮点数

Rust中有f32f64两种浮点数类型,在现代CPU中,两者的速度几乎相同,但f64的精度会更高
Rust中的浮点数是根据IEEE-754标准实现的,这就导致出现了一些问题:

fn main() {
	assert!(0.1+0.2==0.3);
}

//输出:thread 'main' panicked at 'assertion failed: 0.1 + 0.2 == 0.3', src\main.rs:2:5

上述代码在运行时抛出了panic,也就是说Rust认为0.1+0.2不等于0.3。

  • 在十进制下,0.1+0.2肯定等于0.3,但可惜就可惜在,计算机是二进制,存在精度问题,无论如何也不可能零误差的表示我们十进制中的浮点数。如果你想要完全符合真实数字,那么就要有一个无限精度的浮点数才行。
  • 再从Rust语言的角度来说,在Rust中,基本数值类型里,只有f32与f64的比较运算实现的是std::cmp::PartialEq这个trait,也就是部分相等,而并非std::cmp::Eq完全相等。
    Rust中的HashMap与Java等语言相同,使用K-V构成一个entry的方式实现,对于K没有特定类型的限制,但是要求其必须实现了std::cmp::Eq才可以,这也就是说Rust中无法使用浮点数作为Map的Key
    综上,编码过程中要尽量遵守以下内容:
  • 避免在浮点数上测试相等性
  • 当结果在数学上可能存在未定义时,需要格外的小心
    如果仍然需要比较两个浮点数,可以使用以下方式:
(0.1_f64+0.2-0.3).abs() < 0.00001

Nan(Not a number)

Nan指数学上没有定义的结果,例如对负数开平方根。所有跟Nan交互的操作,返回结果都会是Nan,而且Nan也无法进行比较运算。

fn main() {
    let x = (-42.1f32).sqrt();
    if x.is_nan() {
        print!("Is a nan") 
    }
} 

可以通过以上方式判断某变量是否为nan

单元类型

单元类型长这个样:()
例如在main函数的返回值处就用到了单元类型,在Rust中,发散函数才是没有返回值的函数,而main函数不是发散函数,所以有返回值,但没有显式声明,而是隐式的返回单元类型,再例如println!也返回此类型。
同样的,可以使用()作为某一map的value,来实现Set,表示不关注value,只关注key,用法和Golang中的map[T]struct{}相似,不占用任何内存。

语句及表达式(Statement and expression)

Rust的函数体由一系列语句和一个表达式组成,例如:

fn example(a:i32,b:i32) -> i32{
    let x = a+b;
    let y = a-b;
    x-y
}

Statement会执行一些操作,但不会返回值;而expression会在执行操作后返回一个值,因此前两行是语句,最后一行是表达式

Statement

let也是一个语句,因此不会返回值,也就不能将其赋给某个变量

Expression

5+6会返回11,这是一个表达式
let y = 6,y被赋值6,因此6就是一个表达式,返回6
有返回值的函数也是一个表达式,调用宏也是一个表达式

{
	let x = 3;
	x+1
}

上面的代码块是一个表达式,因为其最后返回了x+1的值。如果x+1的后面加上了分号,那么就变成了语句,其实就不再是表达式了。
表达式如果不返回值,会隐式的返回一个单元类型

fn example() {
    let x = 1;
    let y = if x%2==1{
        "odd"
    }else{
        "even"
    };
    let z = if x%2==1{"odd"} else {"even"};
}

if语句块也可以是一个表达式,另外Rust中的三元运算符可以按照上述方式编写

函数

发散函数

当使用!作为函数返回类型时,表示该函数永不返回,往往在提醒用户程序崩溃时,会使用发散函数:

fn occur_error -> ! {
	panic!("Occur Error");
}
posted @ 2023-09-26 23:13  Appletree24  阅读(12)  评论(0编辑  收藏  举报