我found a function to compute a mean并一直在玩它。下面的代码片段会运行,但如果输入中的数据从float变为int,则会发生错误。如何使用浮点数和整数?
use std::borrow::Borrow;
fn mean(arr: &mut [f64]) -> f64 {
let mut i = 0.0;
let mut mean = 0.0;
for num in arr {
i += 1.0;
mean += (num.borrow() - mean) / i;
}
mean
}
fn main() {
let val = mean(&mut vec![4.0, 5.0, 3.0, 2.0]);
println!("The mean is {}", val);
}
答案 0 :(得分:9)
问题中的代码无法编译,因为f64
没有borrow()
方法。此外,它接受的切片不需要是可变的,因为我们没有改变它。这是一个编译和工作的修改版本:
fn mean(arr: &[f64]) -> f64 {
let mut i = 0.0;
let mut mean = 0.0;
for num in arr.iter() {
i += 1.0;
mean += (num - mean) / i;
}
mean
}
要接受整数,该函数必须是泛型。理想情况下,它不仅可以接受整数,还可以接受任何可以转换为f64
的类型,例如f32
或用户提供的数据类型。写一些类似的东西会很好:
fn mean<T>(arr: &[T]) -> f64 {
let mut i = 0.0;
let mut mean = 0.0;
for num in arr.iter() {
i += 1.0;
mean += (num as f64 - mean) / i;
}
mean
}
这不会编译,因为没有为任意x as f64
定义x
。相反,我们需要T
上绑定的特征,该特征定义了将T
值转换为f64
的方法。这正是Into
trait的目的;实现T
的每个类型Into<U>
都定义了into(self) -> U
方法。将T: Into<f64>
指定为特征范围会为我们提供返回into()
的{{1}}方法。
我们还需要请求f64
为T
,以便Rust知道数组中的值不会花费&#34;花费&#34; (移动)转换。由于整数实现Copy
,这对我们来说没问题。然后,工作代码如下所示:
Copy
请注意,这仅适用于定义无损转换为fn mean<T: Into<f64> + Copy>(arr: &[T]) -> f64 {
let mut i = 0.0;
let mut mean = 0.0;
for num in arr.iter() {
i += 1.0;
mean += ((*num).into() - mean) / i;
}
mean
}
fn main() {
let val1 = mean(&vec![4.0, 5.0, 3.0, 2.0]);
let val2 = mean(&vec![4, 5, 3, 2]);
println!("The means are {} and {}", val1, val2);
}
的类型。因此,它适用于f64
,u32
(如上例所示)和较小的整数类型,但它不会接受例如i32
或{{1的向量}},无法无损地转换为i64
。
另请注意,此问题很适合函数式编程习惯用法,例如enumerate()
和fold()
。虽然在这个已经很长的答案的范围之外,写出这样的实现是一个练习hard to resist。