Rust 新手程序员/数字转换
如果我们有一个类型为(例如 u8)的数字,并且我们想将其转换为另一种类型(例如 i32)的数字,我们该如何做呢?数字类型转换的一个重要原则是增加位数总是安全的。然而,反过来可能存在风险,因为我们可能会丢失信息。因此,如果我们正在进行一个“安全”的向上转换,那么有一些简单的方法可以做到这一点。
fn main() {
let number1: u8 = 10;
let number2 = i32::from(number1);
let number3: i32 = number1.into();
}
最后,所有这些都将是 10。注意,对于第三个,我们指定了 number3 的类型为 i32。如果我们没有这样做,它将无法编译,因为编译器必须知道变量的类型。如果我们稍后在需要 i32 的地方使用它,那么编译器可以推断出它是一个 i32。这称为类型推断,它非常有助于减少我们编写的冗余代码量。
如果我们想反过来,从较大的类型转换为较小的类型,最简单的方法是使用关键字“as”进行强制转换。这存在风险,因为如果数字是较小类型无法存储的数字,那么您将得到奇怪的行为。例如
fn main() {
let number1 = -10i32;
let number2 = number1 as u8;
println!("{}", number2);
}
这将打印出 246。注意,我们在 -10 的末尾使用 i32 来放置类型。这只是另一种方法;您可能喜欢或不喜欢它,但这是一种值得了解的选项。打印出 246 的原因是 u8 只能存储从 0 到 255 的数字。从 256 开始的第 10 个数字是 246。然而,您极少会想要依赖这种行为,因此我们改为这样做
fn main() {
let number1 = 10i32;
let number2: u8 = number1.try_into().unwrap();
println!("{}", number2);
}
现在我们必须在 number2 上使用显式类型来表明我们想将其转换为 u8。try_into() 函数尝试将其转换为一个数字并返回一个称为“Result”的类型,该类型指示转换是否成功。unwrap() 意味着我们假设转换成功。如果转换不成功,即另一个数字不能用新的数字类型表示,那么程序将崩溃,这在 Rust 中称为恐慌。由于数字无法正确转换而导致崩溃可能看起来很奇怪,但这是一个重要的概念。如果出了问题,我们想做什么?我们有两个选择:中止并停止运行,或者继续运行并尝试使用我们现有的东西。然而,小的错误会导致看不见的后果。程序通常依赖于我们预期的值或数字。如果我们使用“as”进行转换,我们很容易得到奇怪的意外结果,这些结果会导致程序中更深层次的错误,这些错误非常难以追踪。相反,我们通常希望直接崩溃并能够确定存在错误以及错误发生的位置,从而允许我们修复错误。只有在极少数情况下,我们才希望在数字不匹配时依赖“as”的奇怪行为。
回到上一章的问题,我们想从 get_median() 函数返回一个浮点数。我们可以从函数中返回一个 f64,因为 f64 比 i32 大,所以我们可以使用安全转换方法。
fn get_median(input: Vec<i32>) -> f64 {
let mut array = input;
//sort array
for index1 in 0..array.len() {
for index2 in index1..array.len() {
if array[index2] > array[index1] {
array.swap(index1, index2);
}
}
}
//return median
if array.len() % 2 == 0 {
//even
let middle_value1 = array[array.len() / 2 - 1].into();
let middle_value2 = array[array.len() / 2].into();
let median = (middle_value1 + middle_value2) / 2.0;
return median;
} else {
//odd
let median = array[array.len() / 2].into();
return median;
}
}
注意,因为我们从函数返回一个 f64,所以编译器可以计算出当我们使用 .into() 时,我们想要一个 f64,因此我们不必写出类型。现在这个函数按预期工作,返回正确的中值。