数值类型
整数类型
- 无符号整数只能取正数和0,有符号整数可以取正数负数和0。
- isize和usize类型取决于程序运行的计算机CPU类型,若CPU是32位的,则这两个类型是32位的,若CPU是64位的,则它们是64位的。
- rust整型 默认使用 i32,例如 let i = 1; 那 i 就是 i32类型。
- 整型溢出
- 假设有一个 u8 ,它可以存放从 0 到 255 的值。那么当你将其修改为范围之外的值,比如 256,则会发生整型溢出。
debug
模式 编译下,若存在整形溢出,则程序在编译时因错误而退出。- 当使用
--release
参数进行release 模式构建时,rust不
检测整型溢出,当检测到整型溢出时,rust会按照补码循环溢出,例如在 u8 情况下,256变成0,257变成1。程序不会因错误而退出,但是可能不是你所期望的值。 - 要显式的处理可能的溢出,可以使用标准库针对原始数字类型提供的这些方法:
- 使用
wrapping_*
方法在所有模式下都按照补码循环溢出规则处理。例如 wrapping_add - 如果使用
checked_*
方法时发生溢出,则返回 None 值 - 使用
overflowing_*
方法返回该值和一个指示是否存在溢出的布尔值 - 使用
saturating_*
方法,可以限定计算后的结果不超过目标类型的最大值或低于最小值 - 以下是一个示例代码,然后
cargo run
命令运行代码如下
- 使用
fn main() {
let a: i32 = 2147483647; //整型溢出
let b: i32 = 10;
//wrapping_add
let wrapping_result = a.wrapping_add(b); //简单的相加操作,a+b
println!("Wrapping Add Result: {}", wrapping_result);
//checked_add··············
match a.checked_add(b) {
Some(result) => println!("Checked Add Result: {}", result),
None => println!("Checked Add Overflowed"),
}
// overflowing_add
let (overflowing_result, did_overflow) = a.overflowing_add(b);
println!("Overflowing Add Result: {}", overflowing_result);
println!("Did Overflow: {}", did_overflow);
// saturating_add
let saturating_result = a.saturating_add(b);
println!("Saturating Add Result: {}", saturating_result);
}
浮点类型
- Rust 中浮点类型数字有两种基本类型: f32 和 f64,分别为 32 位(单精度)和 64 位(双精度)大小。默认浮点类型是 f64,在现代的 CPU 中它的速度与 f32 几乎相同,但精度更高。
- 但是浮点数是我们想要数字的近似表达,因此需要避免在浮点数上测试相等性,当结果在数学上可能存在未定义时,需要格外的小心。
NaN
- 对于数学上未定义的结果会产生一个特殊的结果NaN,所有跟NaN交互的操作都会返回一个NaN,而且NaN不能用来比较,可以使用
is_nan()
等方法来判断一个数值是否是NaN,如下
fn main() {
let x = (-42.0_f32).sqrt();
if x.is_nan() {
println!("未定义的数学行为")
}
}
数字运算
Rust 支持所有数字类型的基本数学运算:加法、减法、乘法、除法和取模运算。跟正常的数学运算一样。
位运算
- rust位运算基本上和其它语言一样。
- 示例代码
fn main() {
// 二进制为00000010
let a:i32 = 2;
// 二进制为00000011
let b:i32 = 3;
println!("(a & b) value is {}", a & b);
println!("(a | b) value is {}", a | b);
println!("(a ^ b) value is {}", a ^ b);
println!("(!b) value is {} ", !b);
println!("(a << b) value is {}", a << b);
println!("(a >> b) value is {}", a >> b);
let mut a = a;
// 注意这些计算符除了!之外都可以加上=进行赋值 (因为!=要用来判断不等于)
a <<= b;
println!("(a << b) value is {}", a);
}
运行结果如下
序列
- rust提供了非常简洁的方式来生成连续的数值,例如
1..5
,生成从1到4的连续数字,不包含5,常用于循环当中,序列只允许用于数字或字符类型,例如:
fn main() {
for i in 1..=5 {
println!("{}",i);
}
}
运行如下
有理数和复数
- rust标准库中不包含有理数和复数,但社区已经开发出高质量的rust数值库,可以按以下步骤来引入
num
库:- 创建新工程
cargo new complex-num
然后cd complex-num
- 在
Cargo.toml
中的[dependencies]
下添加一行num = "0.4.0"
- 将
src/main.rs
文件中的main函数替换为下面的代码 - 运行cargo run
- 创建新工程
use num::complex::Complex;
fn main() {
let a = Complex { re: 2.1, im: -1.2};
let b = Complex::new(11.1, 22.2);
let result = a + b;
println("{} + {}i", result.re, result.im)
}
字符类型(char)
- Rust语言中的字符不仅仅是
ASCII
,所有的Unicode
值都可以作为Rust字符,包括单个的中文、日文、韩文、emoji表情符号等等都是合法的字符类型。由于Unicode都是四个字节编码,因此字符类型也是占用四个字节。
布尔类型(bool)
- Rust中的布尔类型有true和false两个可能的值,站内存大小为一个字节。使用布尔类型的场景主要在于流程控制。
单元类型
- 单元类型就是
()
,唯一的值也是(),例如fn main(),main函数就是返回这个单元类型(),例如常见的println!()的返回值也是单元类型()。不占用任何内存。
语句和表达式
- Rust的函数体是由一系列的语句组成,最后由一个表达式来返回值,如下
fn add_with_extra(x: i32, y: i32) -> i32 {
let x = x + 1; // 语句
let y = y + 5; // 语句
x + y // 表达式
}
语句
- 语句完成一个具体的操作,但是不返回值,如下:
let a = 8;
let b: Vec<f64> = Vec::new();
let (a, c) = ("hi", false);
表达式
- 表达式会进行求值,然后返回一个值,表达式可以称为语句的一部分,例如 let y = 6,6就是一个表达式。如果表达式不返回任何值,会隐式的返回一个(),函数没有返回值,那么返回一个(),通过;结尾的语句返回一个()。如下用花括号包裹起来最终返回一个值的语句块也是表达式:
fn main() {
let y = {
let x = 3;
x + 1
};
println!("The value of y is: {}", y);
}
以下函数会隐式返回一个()
use std::fmt::Debug;
fn report<T: Debug>(item: T) {
println!("{:?}", item);
}
以下函数会显式的返回一个()
fn clear(text: &mut String) -> () {
*text = String::from("");
}
注意:表达式不能以分号结尾,否则就会从表达式变成一条语句,再也不会返回一个值。
函数
- Rust函数跟其它语言几乎没什么区别,如下
fn add(i: i32, j: i32) -> i32 {
i + j
}
声明函数的关键字fn
,函数名add()
,参数i
和j
,参数类型和返回值类型都是i32
。
函数要点
- 函数名和变量名使用蛇形命名法,例如
fn add_two() -> {}
。 - 函数位置可以随便放,Rust不关心我们在哪里定义了函数,只要有定义即可。
- Rust是强类型语言,因此需要为每一个函数参数标识它的具体类型。
函数返回
- 在Rust中函数就是表达式,我们可以把函数的返回值直接赋给调用者。函数的返回值就是函数体最后一条表达式的值,也可以使用return提前返回
//这个函数返回表达式x+5的值
fn plus_five(x:i32) -> i32 {
x + 5
}
//该函数若x>5,就提前返回x-5的值,跟其它语言差别不大
fn plus_or_minus(x:i32) -> i32 {
if x > 5 {
return x - 5
}
x + 5
}
fn main() {
let x = plus_five(5);
println!("The value of x is: {}", x);
}
- 永远不返回的发散函数
当!
用作函数返回类型的时候,表示该函数永远不返回,该语法往往用作会导致程序崩溃的函数:
fn dead_end() -> ! {
panic!("你已经到了穷途末路,崩溃吧!");
}