数值类型
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按键的控制符。