数值类型
Rust的数值类型包括整数和浮点数。有如下几种类型:
长度 | 有符号 | 无符号 | 浮点数 |
---|---|---|---|
8-bit | i8 | u8 | |
16-bit | i16 | u16 | |
32-bit | i32(默认) | u32 | f32 |
64-bit | i64 | u64 | f64(默认) |
128-bit | i128 | u128 | |
word | isize | usize |
注: word表示一个机器字长,通常是一个指针的大小,大小和机器有关。64位机器的word是64-bit,32位机器的word是32-bit。
可以在数值字面量后加上类型来表示该类型的数值。例如:
fn main(){ let _a = 33i32; // 直接加类型后缀 let _b = 33_i32; // 使用_分隔数值和类型 let _c = 33_isize; let _d = 33_f32; }
如果数值较长,可以在任意位置处使用下划线_
划分数值,增加可读性。
fn main(){ let _a = 33_333_33_i32; let _b = 3_333_333_i32; let _c = 3_333_333f32; }
当不明确指定变量的类型,也不明确指定数值字面量的类型后缀,Rust默认将整数当作i32类型,浮点数当作f64类型。
fn main(){ // 等价于 let _a: i32 = 33_i32; let _a = 33; // 等价于let _b: f64 = 64.123_f64; let _b = 64.123; }
每种数值类型都有所能存储的最大数值和最小数值。当超出类型的有效范围时,Rust将报错(panic)。例如u8类型的范围是0-255,它无法存储256。
fn main() { let n: i32 = std::i32::MAX; // i32类型的最大值 println!("{}", n + 1); // 编译错误,溢出 }
Rust允许使用0b 0o 0x
来表示二进制、八进制和十六进制的整数。
fn main(){ let a = 0b101_i32; // 二进制整数,i32类型 let b = 0o17; // 八进制整数,i32类型 let c = 0xac; // 十六进制整数,i32类型 println!("{}, {}, {}", a, b, c); // 5, 15, 172 }
数值类型之间默认不会隐式转换,如果需要转换数值类型,可手动使用as
进行转换(as主要用于原始数据类型间的类型转换)。例如3_i32 as u8
表示将i32类型的3转换为u8类型。需注意,宽类型数值转为窄类型数值时,如果溢出,则从高位截断。
fn main(){ assert_eq!(10_i8 as u16, 10_u16); assert_eq!(2525_u16 as i16, 2525_i16); // 有符号类型->有符号类型 assert_eq!(-1_i16 as i32, -1_i32); // 有符号到无符号类型 assert_eq!(-1_i32 as u8, 255_u8); // 范围溢出,截断 assert_eq!(1000_i16 as u8, 232_u8); // 浮点数转整数,小数部分被丢弃 assert_eq!(33.33_f32 as u8, 33_u8); }
Rust数值是一种类型的值,每种类型有自己的方法,因此数值也可以调用它们具有的方法。
fn main(){ // 需注意,下面的数值都加上了类型后缀。 // 这是因为在调用方法的时候,需要知道值的 // 所属类型才能找到这种类型具有的方法 println!("{}", 3_u8.pow(2)); // 9 println!("{}", (-3_i32).abs()); // 3 // 4,计算45的二进制中有多少个1 println!("{}", 45i32.count_ones()); // 4 }
Rust将字节字面量存储为u8类型,字节字面量的表示方式为b'X'
(b后面使用单引号包围单个ASCII字符)。
例如A的ASCII码为65,那么b'A'
完全等价于65u8
。
fn main(){ let a = b'A'; // a的类型自动推导为u8 let b = a - 65; // b的类型也自动推导为u8 println!("{}, {}", a, b); // 65, 0 }
需注意,某些特殊ASCII字符需要使用反斜线转义,例如b'\n', b'\'', b'\\'
。有些控制类的字符无法直接写出来,此时可以使用十六进制法来表示,例如b'\x1b'
表示ESC按键的控制符。